Skip to content

Commit 86f34ee

Browse files
joyeecheungrichardlau
authored andcommitted
v8: implement v8.stopCoverage()
Add a v8.stopCoverage() API to stop the coverage collection started by NODE_V8_COVERAGE - this would be useful in conjunction with v8.takeCoverage() if the user don't want to emit the coverage at the process exit but still want to collect it on demand at some point. PR-URL: #33807 Backport-PR-URL: #36352 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Ben Noordhuis <[email protected]> Reviewed-By: Jiawen Geng <[email protected]> Reviewed-By: Ben Coe <[email protected]>
1 parent 8ddea3f commit 86f34ee

File tree

6 files changed

+73
-2
lines changed

6 files changed

+73
-2
lines changed

doc/api/v8.md

+14-2
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,18 @@ be reset and a new coverage report will be written to the directory specified
227227
by [`NODE_V8_COVERAGE`][].
228228

229229
When the process is about to exit, one last coverage will still be written to
230-
disk.
230+
disk, unless [`v8.stopCoverage()`][] is invoked before the process exits.
231+
232+
## `v8.stopCoverage()`
233+
234+
<!-- YAML
235+
added: REPLACEME
236+
-->
237+
238+
The `v8.stopCoverage()` method allows the user to stop the coverage collection
239+
started by [`NODE_V8_COVERAGE`][], so that V8 can release the execution count
240+
records and optimize code. This can be used in conjunction with
241+
`v8.takeCoverage()` if the user wants to collect the coverage on demand.
231242

232243
## `v8.writeHeapSnapshot([filename])`
233244
<!-- YAML
@@ -524,7 +535,7 @@ A subclass of [`Deserializer`][] corresponding to the format written by
524535
[`Deserializer`]: #v8_class_v8_deserializer
525536
[`Error`]: errors.html#errors_class_error
526537
[`GetHeapSpaceStatistics`]: https://v8docs.nodesource.com/node-13.2/d5/dda/classv8_1_1_isolate.html#ac673576f24fdc7a33378f8f57e1d13a4
527-
[`NODE_V8_COVERAGE`]: cli.html#cli_node_v8_coverage_dir
538+
[`NODE_V8_COVERAGE`]: cli.md#cli_node_v8_coverage_dir
528539
[`Serializer`]: #v8_class_v8_serializer
529540
[`deserializer._readHostObject()`]: #v8_deserializer_readhostobject
530541
[`deserializer.transferArrayBuffer()`]: #v8_deserializer_transferarraybuffer_id_arraybuffer
@@ -534,6 +545,7 @@ A subclass of [`Deserializer`][] corresponding to the format written by
534545
[`serializer.releaseBuffer()`]: #v8_serializer_releasebuffer
535546
[`serializer.transferArrayBuffer()`]: #v8_serializer_transferarraybuffer_id_arraybuffer
536547
[`serializer.writeRawBytes()`]: #v8_serializer_writerawbytes_buffer
548+
[`v8.stopCoverage()`]: #v8_v8_stopcoverage
537549
[`vm.Script`]: vm.html#vm_new_vm_script_code_options
538550
[HTML structured clone algorithm]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
539551
[V8]: https://developers.google.com/v8/

lib/v8.js

+1
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ module.exports = {
293293
DefaultDeserializer,
294294
deserialize,
295295
takeCoverage: profiler.takeCoverage,
296+
stopCoverage: profiler.stopCoverage,
296297
serialize,
297298
writeHeapSnapshot,
298299
};

src/inspector_profiler.cc

+20
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,10 @@ void V8CoverageConnection::TakeCoverage() {
295295
DispatchMessage("Profiler.takePreciseCoverage", nullptr, true);
296296
}
297297

298+
void V8CoverageConnection::StopCoverage() {
299+
DispatchMessage("Profiler.stopPreciseCoverage");
300+
}
301+
298302
void V8CoverageConnection::End() {
299303
Debug(env_,
300304
DebugCategory::INSPECTOR_PROFILER,
@@ -505,6 +509,21 @@ static void TakeCoverage(const FunctionCallbackInfo<Value>& args) {
505509
}
506510
}
507511

512+
static void StopCoverage(const FunctionCallbackInfo<Value>& args) {
513+
Environment* env = Environment::GetCurrent(args);
514+
V8CoverageConnection* connection = env->coverage_connection();
515+
516+
Debug(env,
517+
DebugCategory::INSPECTOR_PROFILER,
518+
"StopCoverage, connection %s nullptr\n",
519+
connection == nullptr ? "==" : "!=");
520+
521+
if (connection != nullptr) {
522+
Debug(env, DebugCategory::INSPECTOR_PROFILER, "Stopping coverage\n");
523+
connection->StopCoverage();
524+
}
525+
}
526+
508527
static void Initialize(Local<Object> target,
509528
Local<Value> unused,
510529
Local<Context> context,
@@ -513,6 +532,7 @@ static void Initialize(Local<Object> target,
513532
env->SetMethod(target, "setCoverageDirectory", SetCoverageDirectory);
514533
env->SetMethod(target, "setSourceMapCacheGetter", SetSourceMapCacheGetter);
515534
env->SetMethod(target, "takeCoverage", TakeCoverage);
535+
env->SetMethod(target, "stopCoverage", StopCoverage);
516536
}
517537

518538
} // namespace profiler

src/inspector_profiler.h

+1
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ class V8CoverageConnection : public V8ProfilerConnection {
9595
void WriteProfile(v8::Local<v8::Object> result) override;
9696
void WriteSourceMapCache();
9797
void TakeCoverage();
98+
void StopCoverage();
9899

99100
private:
100101
std::unique_ptr<inspector::InspectorSession> session_;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
'use strict';
2+
const v8 = require('v8');
3+
v8.stopCoverage();
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
'use strict';
2+
3+
if (!process.features.inspector) return;
4+
5+
require('../common');
6+
const fixtures = require('../common/fixtures');
7+
const tmpdir = require('../common/tmpdir');
8+
const assert = require('assert');
9+
const fs = require('fs');
10+
const { spawnSync } = require('child_process');
11+
12+
tmpdir.refresh();
13+
const intervals = 20;
14+
15+
{
16+
const output = spawnSync(process.execPath, [
17+
'-r',
18+
fixtures.path('v8-coverage', 'stop-coverage'),
19+
'-r',
20+
fixtures.path('v8-coverage', 'take-coverage'),
21+
fixtures.path('v8-coverage', 'interval'),
22+
], {
23+
env: {
24+
...process.env,
25+
NODE_V8_COVERAGE: tmpdir.path,
26+
NODE_DEBUG_NATIVE: 'INSPECTOR_PROFILER',
27+
TEST_INTERVALS: intervals
28+
},
29+
});
30+
console.log(output.stderr.toString());
31+
assert.strictEqual(output.status, 0);
32+
const coverageFiles = fs.readdirSync(tmpdir.path);
33+
assert.strictEqual(coverageFiles.length, 0);
34+
}

0 commit comments

Comments
 (0)