-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Improve performance of Debug.format functions #49487
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -301,19 +301,19 @@ namespace ts { | |
return members.length > 0 && members[0][0] === 0 ? members[0][1] : "0"; | ||
} | ||
if (isFlags) { | ||
let result = ""; | ||
const result: string[] = []; | ||
let remainingFlags = value; | ||
for (const [enumValue, enumName] of members) { | ||
if (enumValue > value) { | ||
break; | ||
} | ||
if (enumValue !== 0 && enumValue & value) { | ||
result = `${result}${result ? "|" : ""}${enumName}`; | ||
result.push(enumName); | ||
remainingFlags &= ~enumValue; | ||
} | ||
} | ||
if (remainingFlags === 0) { | ||
return result; | ||
return result.join("|"); | ||
} | ||
} | ||
else { | ||
|
@@ -326,7 +326,17 @@ namespace ts { | |
return value.toString(); | ||
} | ||
|
||
const enumMemberCache = new Map<any, SortedReadonlyArray<[number, string]>>(); | ||
|
||
function getEnumMembers(enumObject: any) { | ||
// Assuming enum objects do not change at runtime, we can cache the enum members list | ||
// to reuse later. This saves us from reconstructing this each and every time we call | ||
// a formatting function (which can be expensive for large enums like SyntaxKind). | ||
const existing = enumMemberCache.get(enumObject); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As you mentioned, this is one of those things that only really matters for tests. In There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The main benefit at runtime is the debug helpers that we define to use in VS Code's debugger in settings.json, where these helpers are called over and over to show the node types. Some things can be improved later, though. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is there any document describing how you debug TypeScript etc? I have my own ways (mostly using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Making sure that |
||
if (existing) { | ||
return existing; | ||
} | ||
|
||
const result: [number, string][] = []; | ||
for (const name in enumObject) { | ||
const value = enumObject[name]; | ||
|
@@ -335,7 +345,9 @@ namespace ts { | |
} | ||
} | ||
|
||
return stableSort<[number, string]>(result, (x, y) => compareValues(x[0], y[0])); | ||
const sorted = stableSort<[number, string]>(result, (x, y) => compareValues(x[0], y[0])); | ||
enumMemberCache.set(enumObject, sorted); | ||
return sorted; | ||
} | ||
|
||
export function formatSyntaxKind(kind: SyntaxKind | undefined): string { | ||
|
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.
I'm not sure if it's still the case, but in earlier v8 versions if you avoid allocating the array until you have the first element the performance is improved because it doesn't have to re-type the array.
As a result, we have a lot of code that does either of the following:
That said, since this code isn't performance critical, it probably wouldn't help much.
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.
That's an interesting idea; I know that this string addition itself was definitely bad, but I had never (when fixing this kind of code after pprof showing huge allocations) thought about creating a single array with one element to get v8 to do the right thing; the performance boost from just doing
join
was the main significant item.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.
IIRC, this was a performance optimization employed by @vladima back in the day. It still seems to be effective from what I can tell.