Skip to content

Add runtime information about libc versionΒ #48204

@H4ad

Description

@H4ad

This topic already been discussed before in the following issues/PRs:

While this was considered a resolved topic as we can get the information from process.report.getReport, I want to put more focus on the performance implications of not exposing this information.

Current Performance

Below, is the op/s to check if the system is musl using many methods I saw using this code search:

process.report.getReport() x 218 ops/sec Β±4.16% (76 runs sampled)
isMusl x 167 ops/sec Β±1.94% (74 runs sampled)
isMuslByFile x 95,904 ops/sec Β±2.67% (80 runs sampled)
Fastest is isMuslByFile
benchmark.js
const Benchmark = require('benchmark');

const suite = new Benchmark.Suite();

const decoder = new TextDecoder();

const isMusl = () => {
  try {
    const lddPath = decoder.decode(require('child_process').execSync('ldd --version')).includes('musl')
    return lddPath
  } catch (e) {
    return true
  };
}

function isMuslByFile() {
  try {
    return readFileSync('/usr/bin/ldd', 'utf8').includes('musl')
  } catch (e) {
    return true
  }
}

suite.add('process.report.getReport()', function () {
  const id = !process.report.getReport().header.glibcVersionRuntime;
});

suite.add(`isMusl`, function () {
  const result = isMusl();
});

suite.add(`isMuslByFile`, function () {
  const result = isMuslByFile();
});

suite
  // add listeners
  .on('cycle', function (event) {
    console.log(String(event.target));
  })
  .on('complete', function () {
    console.log('Fastest is ' + this.filter('fastest').map('name'));
  })
  .run({
    async: true,
  });

Above, is just the time spent in a benchmark, in real life, v8 will not optimize this function soo much, below the profile of swcx (rust binding for swc).

image

Command: node --cpu-prof swcx/index.js
Profile: swcx.cpuprofile.zip

Implications

These libraries usually implement their own version instead of installing a library like detect-libc to have a standardized way to check if the system is musl. This means that almost every nodejs package that checks if it is musl will increase the startup time by some range of 5~30ms.

But even using detect-libc, it didn't cache the result value if the system is musl, so the problem with initialization is also a problem here, and this library is downloaded 9 million times, which means a lot of time can be saved here.
Actually, detect-libc caches the value after the first run, so if multiple libraries use this lib to check for musl, they can benefit from this cache.

This issue can also affect NPM or any package manager if they decide to follow this RFC: npm/rfcs#519 if they decide to provide support for npm/rfcs#519 (comment). With this implementation, possibly every x64 linux will have some startup penalty but at least this will only be once, as the library no longer needs to do this check.

Conclusion

There is a lot of time that can be saved by just exposing that information directly instead of relying on process.report.getReport. The main benefit will be for many libraries that expose native bindings with NodeJS.

So, I want to raise some feedback about this, especially from @styfle, @Brooooooklyn, @richardlau and @bnoordhuis.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions