Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
231 changes: 217 additions & 14 deletions doc/api/v8.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@
The `node:v8` module exposes APIs that are specific to the version of [V8][]
built into the Node.js binary. It can be accessed using:

```js
```mjs
import v8 from 'node:v8';
```

```cjs
const v8 = require('node:v8');
```

Expand Down Expand Up @@ -92,9 +96,18 @@ terminating the process.
Generating a snapshot is a synchronous operation which blocks the event loop
for a duration depending on the heap size.

```mjs
// Print heap snapshot to the console
import { getHeapSnapshot } from 'node:v8';
import process from 'node:process';
const stream = getHeapSnapshot();
stream.pipe(process.stdout);
```

```js
// Print heap snapshot to the console
const v8 = require('node:v8');
const process = require('node:process');
const stream = v8.getHeapSnapshot();
stream.pipe(process.stdout);
```
Expand Down Expand Up @@ -467,11 +480,70 @@ The V8 options available for a version of Node.js may be determined by running

Usage:

```js
// Print GC events to stdout for one minute.
const v8 = require('node:v8');
v8.setFlagsFromString('--trace_gc');
setTimeout(() => { v8.setFlagsFromString('--notrace_gc'); }, 60e3);
```mjs
import { setFlagsFromString } from 'node:v8';
import { setInterval } from 'node:timers';

// setFlagsFromString to trace garbage collection events
setFlagsFromString('--trace-gc');

// Trigger GC events by using some memory
let arrays = [];
const interval = setInterval(() => {
for (let i = 0; i < 500; i++) {
arrays.push(new Array(10000).fill(Math.random()));
}

if (arrays.length > 5000) {
arrays = arrays.slice(-1000);
}

console.log(`\n* Created ${arrays.length} arrays\n`);
}, 100);

// setFlagsFromString to stop tracing GC events after 1.5 seconds
setTimeout(() => {
setFlagsFromString('--notrace-gc');
console.log('\nStopped tracing!\n');
}, 1500);

// Stop triggering GC events altogether after 2.5 seconds
setTimeout(() => {
clearInterval(interval);
}, 2500);
```

```cjs
const { setFlagsFromString } = require('node:v8');
const { setInterval } = require('node:timers');

// setFlagsFromString to trace garbage collection events
setFlagsFromString('--trace-gc');

// Trigger GC events by using some memory
let arrays = [];
const interval = setInterval(() => {
for (let i = 0; i < 500; i++) {
arrays.push(new Array(10000).fill(Math.random()));
}

if (arrays.length > 5000) {
arrays = arrays.slice(-1000);
}

console.log(`\n* Created ${arrays.length} arrays\n`);
}, 100);

// setFlagsFromString to stop tracing GC events after 1.5 seconds
setTimeout(() => {
console.log('\nStopped tracing!\n');
setFlagsFromString('--notrace-gc');
}, 1500);

// Stop triggering GC events altogether after 2.5 seconds
setTimeout(() => {
clearInterval(interval);
}, 2500);
```

## `v8.stopCoverage()`
Expand Down Expand Up @@ -551,13 +623,37 @@ terminating the process.
Generating a snapshot is a synchronous operation which blocks the event loop
for a duration depending on the heap size.

```js
```mjs
import { writeHeapSnapshot } from 'node:v8';
import { Worker, isMainThread, parentPort } from 'node:worker_threads';
import { fileURLToPath } from 'node:url';

if (isMainThread) {
const __filename = fileURLToPath(import.meta.url);
const worker = new Worker(__filename);

worker.once('message', (filename) => {
console.log(`worker heapdump: ${filename}`);
// Now get a heapdump for the main thread.
console.log(`main thread heapdump: ${writeHeapSnapshot()}`);
});

// Tell the worker to create a heapdump.
worker.postMessage('heapdump');
} else {
parentPort.once('message', (message) => {
if (message === 'heapdump') {
// Generate a heapdump for the worker
// and return the filename to the parent.
parentPort.postMessage(writeHeapSnapshot());
}
});
}
```

```cjs
const { writeHeapSnapshot } = require('node:v8');
const {
Worker,
isMainThread,
parentPort,
} = require('node:worker_threads');
const { Worker, isMainThread, parentPort } = require('node:worker_threads');

if (isMainThread) {
const worker = new Worker(__filename);
Expand Down Expand Up @@ -903,6 +999,71 @@ const stopHookSet = promiseHooks.createHook({
after,
});

// Trigger the hooks by using promises
const promiseLog = (word) => Promise.resolve(word).then(console.log);
promiseLog('Hello');
promiseLog('World');

// To stop a hook, call the function returned at its creation.
stopWatchingInits();
stopWatchingSettleds();
stopWatchingBefores();
stopWatchingAfters();
stopHookSet();
```

```cjs
const { promiseHooks } = require('node:v8');

// There are four lifecycle events produced by promises:

// The `init` event represents the creation of a promise. This could be a
// direct creation such as with `new Promise(...)` or a continuation such
// as `then()` or `catch()`. It also happens whenever an async function is
// called or does an `await`. If a continuation promise is created, the
// `parent` will be the promise it is a continuation from.
function init(promise, parent) {
console.log('a promise was created', { promise, parent });
}

// The `settled` event happens when a promise receives a resolution or
// rejection value. This may happen synchronously such as when using
// `Promise.resolve()` on non-promise input.
function settled(promise) {
console.log('a promise resolved or rejected', { promise });
}

// The `before` event runs immediately before a `then()` or `catch()` handler
// runs or an `await` resumes execution.
function before(promise) {
console.log('a promise is about to call a then handler', { promise });
}

// The `after` event runs immediately after a `then()` handler runs or when
// an `await` begins after resuming from another.
function after(promise) {
console.log('a promise is done calling a then handler', { promise });
}

// Lifecycle hooks may be started and stopped individually
const stopWatchingInits = promiseHooks.onInit(init);
const stopWatchingSettleds = promiseHooks.onSettled(settled);
const stopWatchingBefores = promiseHooks.onBefore(before);
const stopWatchingAfters = promiseHooks.onAfter(after);

// Or they may be started and stopped in groups
const stopHookSet = promiseHooks.createHook({
init,
settled,
before,
after,
});

// Trigger the hooks by using promises
const promisePrint = (word) => Promise.resolve(word).then(console.log);
promisePrint('Hello');
promisePrint('World');

// To stop a hook, call the function returned at its creation.
stopWatchingInits();
stopWatchingSettleds();
Expand Down Expand Up @@ -1396,7 +1557,16 @@ is as follows.

Here's an example.

```js
```mjs
import { GCProfiler } from 'node:v8';
const profiler = new GCProfiler();
profiler.start();
setTimeout(() => {
console.log(profiler.stop());
}, 1000);
```

```cjs
const { GCProfiler } = require('node:v8');
const profiler = new GCProfiler();
profiler.start();
Expand Down Expand Up @@ -1507,8 +1677,37 @@ otherwise, it returns false.
If this method returns false, that does not mean that the string contains some characters not in `Latin-1/ISO-8859-1`.
Sometimes a `Latin-1` string may also be represented as `UTF16`.

```js
```mjs
import { isStringOneByteRepresentation } from 'node:v8';
import { Buffer } from 'node:buffer';

const Encoding = {
latin1: 1,
utf16le: 2,
};
const buffer = Buffer.alloc(100);
function writeString(input) {
if (isStringOneByteRepresentation(input)) {
console.log(`input: '${input}'`);
buffer.writeUint8(Encoding.latin1);
buffer.writeUint32LE(input.length, 1);
buffer.write(input, 5, 'latin1');
console.log(`decoded: '${buffer.toString('latin1', 5, 5 + input.length)}'\n`);
} else {
console.log(`input: '${input}'`);
buffer.writeUint8(Encoding.utf16le);
buffer.writeUint32LE(input.length * 2, 1);
buffer.write(input, 5, 'utf16le');
console.log(`decoded: '${buffer.toString('utf16le', 5, 5 + input.length * 2)}'`);
}
}
writeString('hello');
writeString('你好');
```

```cjs
const { isStringOneByteRepresentation } = require('node:v8');
const { Buffer } = require('node:buffer');

const Encoding = {
latin1: 1,
Expand All @@ -1517,13 +1716,17 @@ const Encoding = {
const buffer = Buffer.alloc(100);
function writeString(input) {
if (isStringOneByteRepresentation(input)) {
console.log(`input: '${input}'`);
buffer.writeUint8(Encoding.latin1);
buffer.writeUint32LE(input.length, 1);
buffer.write(input, 5, 'latin1');
console.log(`decoded: '${buffer.toString('latin1', 5, 5 + input.length)}'\n`);
} else {
console.log(`input: '${input}'`);
buffer.writeUint8(Encoding.utf16le);
buffer.writeUint32LE(input.length * 2, 1);
buffer.write(input, 5, 'utf16le');
console.log(`decoded: '${buffer.toString('utf16le', 5, 5 + input.length * 2)}'`);
}
}
writeString('hello');
Expand Down
Loading