doc: avoid suggesting testing fast api with intense loop · nodejs/node@4ffa756

@@ -26,15 +26,8 @@ for example, they may not trigger garbage collection.

2626

in a snapshot (either the built-in or a user-land one). Please refer to the

2727

[binding functions documentation](../../src/README.md#binding-functions) for more

2828

information.

29-

* To test fast APIs, make sure to run the tests in a loop with a decent

30-

iterations count to trigger relevant optimizations that prefer the fast API

31-

over the slow one.

32-

* In debug mode (`--debug` or `--debug-node` flags), the fast API calls can be

33-

tracked using the `TRACK_V8_FAST_API_CALL("key")` macro. This can be used to

34-

count how many times fast paths are taken during tests. The key is a global

35-

identifier and should be unique across the codebase.

36-

Use `"binding_name.function_name"` or `"binding_name.function_name.suffix"` to

37-

ensure uniqueness.

29+

* Fast API functions must be tested following the example in

30+

[Test with Fast API path](#test-with-fast-api-path).

3831

* The fast callback must be idempotent up to the point where error and fallback

3932

conditions are checked, because otherwise executing the slow callback might

4033

produce visible side effects twice.

@@ -175,40 +168,47 @@ A typical function that communicates between JavaScript and C++ is as follows.

175168

v8::FastApiCallbackOptions& options);

176169

```

177170178-

* In the unit tests:

179-180-

Since the fast API function uses `TRACK_V8_FAST_API_CALL`, we can ensure that

181-

the fast paths are taken and test them by writing tests that force

182-

V8 optimizations and check the counters.

183-184-

```js

185-

// Flags: --expose-internals --no-warnings --allow-natives-syntax

186-

'use strict';

187-

const common = require('../common');

188-189-

const { internalBinding } = require('internal/test/binding');

190-

// We could also require a function that uses the internal binding internally.

191-

const { divide } = internalBinding('custom_namespace');

192-193-

// The function that will be optimized. It has to be a function written in

194-

// JavaScript. Since `divide` comes from the C++ side, we need to wrap it.

195-

function testFastPath(a, b) {

196-

return divide(a, b);

197-

}

198-199-

eval('%PrepareFunctionForOptimization(testFastPath)');

200-

// This call will let V8 know about the argument types that the function expects.

201-

assert.strictEqual(testFastPath(6, 3), 2);

202-203-

eval('%OptimizeFunctionOnNextCall(testFastPath)');

204-

assert.strictEqual(testFastPath(8, 2), 4);

205-

assert.throws(() => testFastPath(1, 0), {

206-

code: 'ERR_INVALID_STATE',

207-

});

208-209-

if (common.isDebug) {

210-

const { getV8FastApiCallCount } = internalBinding('debug');

211-

assert.strictEqual(getV8FastApiCallCount('custom_namespace.divide.ok'), 1);

212-

assert.strictEqual(getV8FastApiCallCount('custom_namespace.divide.error'), 1);

213-

}

214-

```

171+

### Test with Fast API path

172+173+

In debug mode (`./configure --debug` or `./configure --debug-node` flags), the

174+

fast API calls can be tracked using the `TRACK_V8_FAST_API_CALL("key")` macro.

175+

This can be used to count how many times fast paths are taken during tests. The

176+

key is a global identifier and should be unique across the codebase.

177+

Use `"binding_name.function_name"` or `"binding_name.function_name.suffix"` to

178+

ensure uniqueness.

179+180+

In the unit tests, since the fast API function uses `TRACK_V8_FAST_API_CALL`,

181+

we can ensure that the fast paths are taken and test them by writing tests that

182+

force V8 optimizations and check the counters.

183+184+

```js

185+

// Flags: --expose-internals --no-warnings --allow-natives-syntax

186+

'use strict';

187+

const common = require('../common');

188+189+

const { internalBinding } = require('internal/test/binding');

190+

// We could also require a function that uses the internal binding internally.

191+

const { divide } = internalBinding('custom_namespace');

192+193+

// The function that will be optimized. It has to be a function written in

194+

// JavaScript. Since `divide` comes from the C++ side, we need to wrap it.

195+

function testFastPath(a, b) {

196+

return divide(a, b);

197+

}

198+199+

eval('%PrepareFunctionForOptimization(testFastPath)');

200+

// This call will let V8 know about the argument types that the function expects.

201+

assert.strictEqual(testFastPath(6, 3), 2);

202+203+

eval('%OptimizeFunctionOnNextCall(testFastPath)');

204+

assert.strictEqual(testFastPath(8, 2), 4);

205+

assert.throws(() => testFastPath(1, 0), {

206+

code: 'ERR_INVALID_STATE',

207+

});

208+209+

if (common.isDebug) {

210+

const { getV8FastApiCallCount } = internalBinding('debug');

211+

assert.strictEqual(getV8FastApiCallCount('custom_namespace.divide.ok'), 1);

212+

assert.strictEqual(getV8FastApiCallCount('custom_namespace.divide.error'), 1);

213+

}

214+

```