Description
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.
- 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);
- 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
- Run the node script via with
--enable-source-maps
, likenode --enable-source-maps index.js
- 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.
- Repeat the load tests with source-maps disabled (which is obviously faster, but just to set a baseline)
node index.js
- 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
- 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).
- 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
- 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. - 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.
- 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