node-source-map-support
node-source-map-support copied to clipboard
Discuss performance impact in readme
Should this be used in production?
Does it have any general performance penalty, or does it only do any extra work (sourcemap-parsing/traversing) when an error stack trace is actually read?
It would be good to answer these questions in the readme.
+1
Hi, I would love to know more about performance too.
When are the sourcemaps loaded? is it when corresponding js file is require
d?
I'd like to know if this can be safely used in production as well.
+1
+1
@evanw I guess you should address this to increase the adoption of your library.
I can comment that this library can have a very significant impact on performance in certain situations. I have a site that uses webworkers to fetch and display lots of image data and when browser-source-map-support.js
is included it goes from taking 2.3s to load all of the images to 7.6s (the only difference being including the browser-source-map-support.js
script). In addition, without the library while the client is loading content everything stays very responsive (because all the work is being done on the webworker thread) but with the library installed, the client is significantly bogged down.
I haven't really dug into the source code of source-map-support
to identify what might be causing this behavior, but I would caution against using this in production.
Any updates on this?
Did someone found a piece of answer? Thank you
I found here this:
"'.map' files are loaded only with opened DevTools""
Is it related to this issue?
Is it related to this issue?
No, that is how the browser works, but when this package is loaded it will always load the map files ☺️
Of course using it in production is a significant overhead. Just a brief look at source-map-support/register
(and deeper) shows 560 LOC + requiring path
and source-map
. Anyway great library, thanks to the authors!!
When you say significant, what exactly does that mean? Just 506 lines of code and requiring path
and source-map
in the grand scheme of running a server is not really something to measure significant performance impact surely? We're not talking about server code size here... We're talking about real performance concerns in regular server use.
I would really like to hear some insight from the authors or other on this. Could we use this in production? Having nice source maps when things go wrong in production is nice too - but obviously if it is significantly impacting performance then I'd rather have it off.
@lostpebble I meant it is significant if it is not necessary in production, so if that's the case, it should definitely be removed.
Then, significant is not a unit of measure like kilogram. Hence it is subjective and depends on the case, requirements etc. When talking about performance the best thing to do is benchmarks. Do it, compare results with and without the lib, and see if it is OK or not for you.
For me personally loading 560 LOC in production (i.e. if it is necessary only on dev) from a single library is significant. For others may be not.
That said, again big thanks to the authors.
@anurbol I understand what you're getting at - and sure, it is quite heavy to add to your production code. But what I'd really to know (and I think the original post is about) is the actual performance impact of having this running on your server. Code / dependency tree size doesn't relate directly to performance to me.
Your comment almost made me remove this dependency from production in the future completely - but upon reading it again I don't think its fair to say that there is a significant overhead because of those reasons.
I'll agree that it might be significant perhaps if your use-case was to load up servers for a single process and destroy them soon afterwards - like maybe Cloud Functions / Lambdas. Then all those extra LOC and dependencies could have a real impact, since we'd care more about startup time.
In any case, would love to hear more input from the creators or others in the know about this.
@lostpebble
When talking about performance the best thing to do is benchmarks. Do it, compare results with and without the lib, and see if it is OK or not for you.
That's great and all, but there are many edge cases you won't be able to benchmark for and could run into serious issues in production down the line.
I'm just appealing for some kind of general consensus about regular server use and the performance impact of this library from people in the know. As this issue shows, there are many others who are curious too and I don't think that's unreasonable.
Ran into the same question and, since the answer is lacking, decided to put it to the test: ran 25k HTTP request through a Koa server (so only tested in NodeJS) with and without source-map-support installed, without any exceptions being thrown.
Result: no measurable difference between the runs with or without source-map-support enabled: getting a deviation of max 1% between runs and that deviation is not split by runs with or without support enabled.
A quick look at the code also reveals that the support will only have a runtime impact (by default) on:
- Error.prepareStackTrace: gets patched to 'convert' the stacktrace
- process.emit: gets patched to intercept 'uncaughtException' events to 'convert' the stacktrace
So, looks like there should only be a performance impact when getting the stacktrace (for logging for example) what actual exceptions occur.
So, although not an expert in this library, I'd say it's save to use in production, as I don't mind the little extra overhead in case of exceptions if that will aid investigating problems :-)
Looks like for newer NodeJS versions source-map-support
is no longer needed (strictly speaking) given NodeJS now supports the --enable-source-maps
CLI flag out of the box (also see https://github.com/loopbackio/loopback-next/issues/6393).
However I've noticed that using --enable-source-maps
can significantly slow down the start-up time of NodeJS applications. I'm wondering whether some other folks in this thread have evaluated both options and what you've landed on. Given the point @p-bakker made above it seems quite attractive to stick with source-map-support
.
I'd also be curious to hear if anyone compares the performance of source-map-support
against @cspotcode/source-map-support
. We use a newer version of the underlying source-map consumer which has some WASM components for speed. Node's internal source-map library is, I believe, implemented as plain JS.
Theoretically, this means @cspotcode/source-map-support
can be faster than both node's --enable-source-maps
and source-map-support
, but I haven't benchmarked this.
@schickling we have seen the same thing with larger builds using node's native --enable-source-maps
However I've noticed that using --enable-source-maps can significantly slow down the start-up time of NodeJS applications.
Same – see https://github.com/nodejs/node/issues/41541
Thought I'd add to the conversation - I put together a very simple demo repository that does a timing test for various combinations of node runtime, compiler, and native / 3rd party sourcemap support.
https://github.com/mjpowersjr/source-map-performance-demo
Thanks for putting that together; I posted a few questions here: mjpowersjr/source-map-performance-demo#1
Some of the comparisons appear to be apples-and-oranges, which is not at all a bad thing, but it helps to understand the differences.
I have updated the benchmark to fix bugs and test that the generated stack traces are correct: https://github.com/mjpowersjr/source-map-performance-demo/pull/2 https://github.com/nodejs/node/issues/42417#issuecomment-1079374441
Both --enable-source-maps
and -r source-map-support/register
emit incorrect stack traces. -r @cspotcode/source-map-support/register
is correct. Please don't take my word for it, and check the code to confirm.
--enable-source-maps
is extremely slow and I don't know why.
Results for 10000 stack traces.
node | compiler | options | stack_traces_correct | elapsed_ms |
---|---|---|---|---|
14.19.1 | esbuild | --enable-source-maps | ❌ | 366404 |
14.19.1 | esbuild | -r @cspotcode/source-map-support/register | ✅ | 652 |
14.19.1 | esbuild | -r source-map-support/register | ❌ | 807 |
14.19.1 | esbuild | 230 | ||
14.19.1 | tsc | --enable-source-maps | ❌ | 1916 |
14.19.1 | tsc | -r @cspotcode/source-map-support/register | ✅ | 673 |
14.19.1 | tsc | -r source-map-support/register | ❌ | 642 |
14.19.1 | tsc | 268 | ||
16.14.2 | esbuild | --enable-source-maps | ❌ | 358514 |
16.14.2 | esbuild | -r @cspotcode/source-map-support/register | ✅ | 542 |
16.14.2 | esbuild | -r source-map-support/register | ❌ | 748 |
16.14.2 | esbuild | 222 | ||
16.14.2 | tsc | --enable-source-maps | ❌ | 1870 |
16.14.2 | tsc | -r @cspotcode/source-map-support/register | ✅ | 547 |
16.14.2 | tsc | -r source-map-support/register | ❌ | 576 |
16.14.2 | tsc | 236 | ||
17.8.0 | esbuild | --enable-source-maps | ❌ | 367329 |
17.8.0 | esbuild | -r @cspotcode/source-map-support/register | ✅ | 598 |
17.8.0 | esbuild | -r source-map-support/register | ❌ | 737 |
17.8.0 | esbuild | 202 | ||
17.8.0 | tsc | --enable-source-maps | ❌ | 1726 |
17.8.0 | tsc | -r @cspotcode/source-map-support/register | ✅ | 539 |
17.8.0 | tsc | -r source-map-support/register | ❌ | 535 |
17.8.0 | tsc | 244 |