You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
run this super basic serverless offline setup with sls offline, and sent a request to the exposed endpoint: curl -X POST http://localhost:3000/dev/hello
What did you expect to see?
expect a small increase in the function Duration
What did you see instead?
offline: POST /dev/hello (λ: hello)
Some modules (@hapi/hapi) were already required when their respective plugin was loaded, some plugins might not work. Make sure the SDK is setup before you require in other modules.
new NodeTracerProvider(): 5764.306ms
offline: (λ: hello) RequestId: ckjr4lmce0005sep3fg492vr1 Duration: 5904.73 ms Billed Duration: 6000 ms
Additional context
As you can see, calling new NodeTracerProvider(); is taken ~5 seconds (tested multiple times on my setup).
Profiling the issue shows that this section from PluginLoader in @opentelemetry/node is to taking most of the time:
This algorithm is very inefficient, running in O(requiredModules)*O(modulesToHook) which can be quite large (in the setup for the above example, alreadyRequiredModules.length is 4687 and modulesToHook.length is 14 (and expected to grow over time as more plugins are added).
The points of inefficiency are:
calling the io-blocking, synchronous require.resolve(name) function from within a loop (alreadyRequiredModules.find), inside a try-catch, where the value is not expected to change over iterations.
since alreadyRequiredModules is an array of strings, finding over it takes O(n) (in the above case, 4687 string comparisons per plugin), where we can directly search for the value on the keys of require.cache in O(1) with hasOwnProperty.
I'll create a PR soon with a suggestion for performence fix, which on my setup, reduces the above section runtime from ~5000ms to just 3ms
The text was updated successfully, but these errors were encountered:
I'm guilty for this code, however i'm surpised that alreadyRequiredModules.length is that high since we are supposed to be the first module required (so require.cache should be quite small in theory).
Anyway that would explain a behavior i have with my one of my applications running at @reelevant-tech where it would take >20s to startup :/
@vmarchaud I assume that in most cases the required array is small.
In my case, the serverless framework is responsible for running the lambda and initializing otel, which happens after 4800 packages have already been loaded by the framework.
@blumamir Well we only have one or two packages loaded before otel is loaded in our case and we still saw massive slowdown when enabling otel, i guess that "most cases" is smaller than we can assume with common sense.
@vmarchaud I agree.
Thanks for commenting and reviewing the issue.
Could be great if you can take a look on the PR when you have time, so it can go into the next release :)
What version of OpenTelemetry are you using?
v0.14.0 (latest)
What version of Node are you using?
12
Please provide the code you used to setup the OpenTelemetry SDK
handler.js
package.json
serverless.yml
What did you do?
run this super basic serverless offline setup with
sls offline
, and sent a request to the exposed endpoint:curl -X POST http://localhost:3000/dev/hello
What did you expect to see?
expect a small increase in the function Duration
What did you see instead?
Additional context
As you can see, calling
new NodeTracerProvider();
is taken ~5 seconds (tested multiple times on my setup).Profiling the issue shows that this section from
PluginLoader
in@opentelemetry/node
is to taking most of the time:This algorithm is very inefficient, running in O(requiredModules)*O(modulesToHook) which can be quite large (in the setup for the above example,
alreadyRequiredModules.length
is 4687 andmodulesToHook.length
is 14 (and expected to grow over time as more plugins are added).The points of inefficiency are:
require.resolve(name)
function from within a loop (alreadyRequiredModules.find
), inside a try-catch, where the value is not expected to change over iterations.alreadyRequiredModules
is an array of strings,find
ing over it takes O(n) (in the above case, 4687 string comparisons per plugin), where we can directly search for the value on the keys ofrequire.cache
in O(1) withhasOwnProperty
.I'll create a PR soon with a suggestion for performence fix, which on my setup, reduces the above section runtime from ~5000ms to just 3ms
The text was updated successfully, but these errors were encountered: