Skip to content

--enable-source-maps is unnecessarily slow with large source files #41541

Closed
@cstickel

Description

@cstickel

Version

v16.13.2

Platform

5.13.0-22-generic #22-Ubuntu x86_64 x86_64 x86_64 GNU/Linux

Subsystem

No response

What steps will reproduce the bug?

I know --enable-source-maps is experimental and it's maybe an edge case, because the js files are only large enough the show the effect if they are bundled, which might in most cases not be the case. However, hopefully the bug report still helps to improve the feature.

  1. Create a large typescript file that accesses a stack trace, for example:
const http = require('http');

const foo = `
testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest
testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest
!! add another 40.000 lines here to make the file around 4mb in size !!
testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest
testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest
`;

http.createServer((request, response) => {
  response.writeHead(200);
  console.log(new Error().stack);
  response.end();
}).listen(3000);
  1. Compile the typescript file to javascript with source-maps (it doesn't matter if it's internal or extra file, both will work) tsc --sourceMap index.ts
  2. Run the node script via with --enable-source-maps, like node --enable-source-maps index.js
  3. Throw some requests against the running service, for example with k6, artillery or similar (like ~ 50-100 requests a second should be enough to show the effect)

=> The first requests will be quite fast, but then they get slower and slower.

  1. Repeat the load tests with source-maps disabled (which is obviously faster, but just to set a baseline) node index.js
  2. Repeat the load tests with source-map-support node -r source-map-support/register index.js

=> considering source-maps obviously has a performance impact, but it's neglectable with the source-map-support library, even in production for most cases (even if there are a lot of accesses to error stacks)

How often does it reproduce? Is there a required condition?

Always if the javascript file is large enough and error stacks are accessed quick enough.

What is the expected behavior?

Similar performance to source-map-support.

What do you see instead?

A heavy performance impact for using native source map support.

Additional information

  1. In the simplified example to reproduce the behaviour only the transpiled source file gets large, the source-map is super simple, because it's only a single string that makes the source file large. Still this heavily impacts the performance. With real applications the effect seems to be much worse (like 10 failing requests a second can kill a service in a small to medium service).
  2. That the performance impact is neglectable with the source-map-support library shows that it's likely not a general problem with source-map-support (like that it just has this overhead to process it), but that it's a problem with the specific implementation of the node native source-map support
  3. A real world example of the problem is for example a typescript service, built on some framework (NestJs, Koa, etc). If it's compiled to a single file, for example with esbuild it's getting quite fast super big. Having source-map support in the logs heavily improves the debugging of errors. If now for some reason quite some requests fail, the whole service will go down. Again, of course --enable-source-maps is experimental and not meant to be used in production environments, but still I think this needs to be fixed if it ever should be non experimental.
  4. Maybe until the performance is improved there should be an additional hint on the docs to tell people to use source-map-support instead, just because people might prefer the native solution, especially because, even if it's experimental, it's around there since 2019 already.
  5. If it helps if I provide the code to reproduce additionally to the description above I would be happy to.

Some data from artillery, just for everyone who is not reproducing it on it's own (of course this stats heavily depend on the machine they are executed on, but the tendency should be the same everywhere):

With node --enable-source-maps index.js (native source maps)

http.request_rate: ............................................................. 80/sec
http.requests: ................................................................. 4800
http.codes.200: ................................................................ 4800
http.responses: ................................................................ 4800
http.response_time:
  min: ......................................................................... 50
  max: ......................................................................... 2012
  median: ...................................................................... 1620
  p95: ......................................................................... 1939.5
  p99: ......................................................................... 1978.7

=> as it already stacks up load for more than 60 sec or more requests per secound would lead to timeouts

With node index.js (no source maps)

http.request_rate: ............................................................. 80/sec
http.requests: ................................................................. 4800
http.codes.200: ................................................................ 4800
http.responses: ................................................................ 4800
http.response_time:
  min: ......................................................................... 0
  max: ......................................................................... 39
  median: ...................................................................... 1
  p95: ......................................................................... 3
  p99: ......................................................................... 6

10 times more requests

http.request_rate: ............................................................. 800/sec
http.requests: ................................................................. 48000
http.codes.200: ................................................................ 48000
http.responses: ................................................................ 48000
http.response_time:
  min: ......................................................................... 0
  max: ......................................................................... 145
  median: ...................................................................... 2
  p95: ......................................................................... 16.9
  p99: ......................................................................... 37.7

With node -r source-map-support/register index.js (source-map-support)

http.request_rate: ............................................................. 80/sec
http.requests: ................................................................. 4800
http.codes.200: ................................................................ 4800
http.responses: ................................................................ 4800
http.response_time:
  min: ......................................................................... 0
  max: ......................................................................... 49
  median: ...................................................................... 2
  p95: ......................................................................... 4
  p99: ......................................................................... 6

10 times more requests

http.request_rate: ............................................................. 752/sec
http.requests: ................................................................. 48000
http.codes.200: ................................................................ 48000
http.responses: ................................................................ 48000
http.response_time:
  min: ......................................................................... 0
  max: ......................................................................... 182
  median: ...................................................................... 3
  p95: ......................................................................... 19.9
  p99: ......................................................................... 55.2

Metadata

Metadata

Assignees

No one assigned

    Labels

    help wantedIssues that need assistance from volunteers or PRs that need help to proceed.source mapsIssues and PRs related to source map support.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions