microsoft / vscode-js-debug

A DAP-compatible JavaScript debugger. Used in VS Code, VS, + more
MIT License
1.67k stars 283 forks source link

Incremental Performance Degradation with session.customRequest("variables") Calls #2119

Closed neklesayurii closed 3 weeks ago

neklesayurii commented 3 weeks ago

I've noticed that each time I call session.customRequest("variables") within a single debug session, the response time increases. Restarting the debugger is the only way I've found to reset this slowdown, but I'd love to find a way to clear or reset any internal state or cache that might be causing this performance drop. (I try to dump stack variables during debugging in extension)

System Info:

Example Timing

for (let i = 0; i < 30; ++i) {
  const start = performance.now();
  await this.session.customRequest("variables", { variablesReference: variable.variablesReference });
  console.log("Time elapsed:", performance.now() - start);
}
Time elapsed:  11.290199999999459
Time elapsed:  11.23530000000028
Time elapsed:  12.20679999999993
...
Time elapsed:  34.46030000000246
Time elapsed:  33.31810000000041
Time elapsed:  36.91250000000218
Time elapsed:  34.52990000000136
Time elapsed:  37.4291000000012

I'm unsure if this is an issue with DAP or the debugger itself, but any tips on handling this without needing a full restart would be great!

connor4312 commented 3 weeks ago

DAP is just a protocol, this would be in the JS debugger

neklesayurii commented 3 weeks ago

Thanks for your quick reply, and I'm sorry for the mix-up

connor4312 commented 3 weeks ago

I believe this is because we use a custom function sent to the runtime to generate property previews. This causes a new 'script' to be parsed and evaluated in the runtime. Unfortunately, CDP does not give us a way to 'release' these scripts, nor reuse a script/function that we can call again for each variable without a new script being parsed.

However, I observe that with support for clickable functions, we now call this for each function in a scope eagerly, which makes certain scopes like global scopes much more expensive.

https://github.com/microsoft/vscode-js-debug/blob/4e9f6b8cee28ea0cfaadcee586e2230ee55f9d4d/src/adapter/variableStore.ts#L979-L982

Instead, we can just call the fast Runtime.getProperties which returns the location data we need without eagerly getting the representation for all properties.