-
Notifications
You must be signed in to change notification settings - Fork 349
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
perf: Replacing "else if" with a "switch case" statement to improve Typescript performance #1142
Conversation
…ipt performance I generated a trace from the build process and using [typescript-analyze-trace](https://github.com/microsoft/typescript-analyze-trace) to analyze the hotspots. It turns out that time is spent in this kind of code: ``` if (object.choice?.$case === "aNumber" && object.choice?.value !== undefined && object.choice?.value !== null) { message.choice = { $case: "aNumber", value: object.choice.value }; } else if ( object.choice?.$case === "aString" && object.choice?.value !== undefined && object.choice?.value !== null ) { message.choice = { $case: "aString", value: object.choice.value }; } else if ( //... ``` The previous PR I opened adding "else if" does nothing regarding Typescript perf. With "else if", my test file trace looks like this: ``` npx analyze-trace traceDir Hot Spots ├─ Check file /home/dan/projects/ts-proto/integration/large/messages.ts (31108ms) │ ├─ Check deferred node from (line 6267, char 3) to (line 6539, char 4) (13123ms) │ ├─ Check deferred node from (line 15342, char 3) to (line 15591, char 4) (7092ms) │ ├─ Check deferred node from (line 10849, char 3) to (line 11059, char 4) (4460ms) │ ├─ Check deferred node from (line 17320, char 3) to (line 17496, char 4) (2146ms) │ ├─ Check deferred node from (line 3720, char 3) to (line 3832, char 4) (610ms) │ └─ Check deferred node from (line 8791, char 3) to (line 8915, char 4) (516ms) └─ Check file /home/dan/projects/ts-proto/node_modules/typescript/lib/lib.dom.d.ts (1109ms) ``` Now, with this commit, I'm replace else if with switch statement. The analysis of the build looks like this: ``` Hot Spots ├─ Check file /home/dan/projects/ts-proto/integration/large/messages.ts (3139ms) │ └─ Check deferred node from (line 6278, char 3) to (line 6573, char 4) (525ms) └─ Check file /home/dan/projects/ts-proto/node_modules/typescript/lib/lib.dom.d.ts (617ms) ``` The biggest switch statement takes 525ms to analyze (down from 13seconds with "else if") Implementation-wise, the hardest part is knowning when to close the switch statement. I'm doing a test at the beginning of each loop and at the very end of the function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! Great PR @moufmouf , thank you! I get tracking when to close the switch
is annoying, but your in-source comments made it very easy to follow what's going on.
|
||
// add a check for each incoming field | ||
messageDesc.field.forEach((field) => { | ||
const fieldName = getFieldName(field, options); | ||
const messageProperty = getPropertyAccessor("message", fieldName); | ||
const objectProperty = getPropertyAccessor("object", fieldName); | ||
|
||
if (currentSwitchTarget && !isWithinOneOfThatShouldBeUnion(options, field)) { | ||
// We are exiting a switch, we need to close it |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice, thanks for the in-source comment!
Woah! Merged in 28 minutes. You are a hell of a maintainer. Thanks for all you are doing @stephenh ! |
🎉 This issue has been resolved in version 2.4.2 🎉 The release is available on: Your semantic-release bot 📦🚀 |
This version contains a performance fix for Typescript 5.1+. See stephenh/ts-proto#1142
This is a follow-up (and solution) to #1135 and #1141
I generated a trace from the build process and using typescript-analyze-trace to analyze the hotspots.
It turns out that time is spent almost exclusively in this kind of code:
The previous PR I opened adding "else if" does nothing regarding Typescript perf.
With "else if", my test file trace looks like this:
Now, with this commit, I'm replace
else if
with aswitch
statement.The analysis of the build looks like this:
The biggest
switch
statement takes 525ms to analyze (down from 13seconds withelse if
)Implementation-wise, the hardest part is knowing when to close the switch statement. I'm doing a test at the beginning of each loop and at the very end of the function.