Search code examples
node.jsprofilingv8

How to make best use out of V8's Profiler.takePreciseCoverage's return data


I've some code that outputs Profiler.takePreciseCoverage's data as JSON. Currently I can make use out of only the count and see that a function named fibonacci is running too many times. I don't know how to interpret the other data. Is there a visualizer for this? How do I make the best use out of this data?

const inspector = require("node:inspector");
const promisify = require("util").promisify;

const session = new inspector.Session();
session.connect();
const sessionPost = promisify(session.post).bind(session);

const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

async function main() {
    await sessionPost("Profiler.enable");
    await sessionPost(
      "Profiler.startPreciseCoverage",
      { callCount: true, detailed: true },
    );

    await sleep(5000);

    const data = await sessionPost(
      "Profiler.takePreciseCoverage",
    );

    await sessionPost("Profiler.stopPreciseCoverage");
    await sessionPost("Profiler.disable");

    console.log(JSON.stringify(data.result, null, 4));
}

main();

The above code outputs this:

[
    {
        "scriptId": "483",
        "url": "file:///home/do/codes/experiment/v8-heapsnapshot/index.js",
        "functions": [
            {
                "functionName": "fibonacci",
                "ranges": [
                    {
                        "startOffset": 290,
                        "endOffset": 384,
                        "count": 7892
                    }
                ],
                "isBlockCoverage": false
            },
            {
                "functionName": "sleep",
                "ranges": [
                    {
                        "startOffset": 582,
                        "endOffset": 639,
                        "count": 6
                    }
                ],
                "isBlockCoverage": false
            },
...

Solution

  • startOffset and endOffset are character offsets in the file.

    The primary purpose that the coverage infrastructure was designed for is checking whether your tests cover your entire code base. If, for example, you have an if-block that your tests never enter, the offsets based coverage information can help you determine that.

    (I don't know any existing visualizers, but that doesn't mean there aren't any; I haven't looked.)

    If you care about investigating/improving performance (which is what people typically mean when they say "profiling"), then I don't think coverage data will be very useful. Even if a given line (or, more accurately: control flow block) is executed many times, that doesn't necessarily mean that that line is actually causing performance problems.