-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
[Babel 8] perf: Improve traverse performance #16965
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
Conversation
Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/58733 |
The CI failure is related, which is a bit bad. |
0a1208d
to
e9bb192
Compare
"b", | ||
"b", | ||
], | ||
] |
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.
Technically Jest's CI failure is not a bug.
The new behavior seems to make more sense than the old one.
Previously we didn't traverse the emptyStatement
due to
babel/packages/babel-traverse/src/context.ts
Lines 34 to 56 in a6aa8a9
shouldVisit(node: t.Node): boolean { | |
const opts = this.opts as Visitor; | |
if (opts.enter || opts.exit) return true; | |
// check if we have a visitor for this node | |
if (opts[node.type]) return true; | |
// check if we're going to traverse into this node | |
const keys: Array<string> | undefined = VISITOR_KEYS[node.type]; | |
if (!keys?.length) return false; | |
// we need to traverse into this node so ensure that it has children to traverse into! | |
for (const key of keys) { | |
if ( | |
// @ts-expect-error key is from visitor keys | |
node[key] | |
) { | |
return true; | |
} | |
} | |
return false; | |
} |
babel/packages/babel-traverse/src/context.ts
Lines 92 to 99 in a6aa8a9
for (let key = 0; key < container.length; key++) { | |
const node = container[key]; | |
if (node && this.shouldVisit(node)) { | |
queue.push(this.create(parent, container, key, listKey)); | |
} | |
} | |
return this.visitQueue(queue); |
contexts
and the queue was not added correctly.
Old snapshots
expect(logs).toMatchInlineSnapshot(`
Array [
Array [
"a",
],
Array [
"a",
"b",
"b",
"b",
"b",
],
]
`);
Of course we should avoid this change in non-major releases anyway, because it will affect Jest users.
@@ -335,16 +335,65 @@ describe("modification", function () { | |||
); | |||
}); | |||
|
|||
it("the exported expression", 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.
Q: Why is the test "the exported expression" removed? The new test seems drastically different than the previous test.
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.
Oh, it looks like it was removed accidentally. Thanks for noticing it!
e9bb192
to
bd24696
Compare
bd24696
to
2c580d6
Compare
2c580d6
to
c2c16cf
Compare
c2c16cf
to
77bc11b
Compare
To avoid possible regressions, I moved it to Babel 8. |
Fixes #1, Fixes #2
This PR is a bit weird because I can't fully explain the benchmark results. Discussions are welcome!
Overall time reduction of 10%-20, with one benchmark regression (~15%) that can be fixed by merging #16964.
Also reduced reliance on the global cache and almost no global cache in Babel 8.
There are two changes in this PR
parentPath
Each of them alone gives little or no improvement, but together the performance improvement is much larger.
Even weirder is that there is a benchmark
mjs-cjs/ts-checker
that drops by more than 15%, and it has the same drop when only the second change is made, whilejs-node6/typescript-5.6.2
(larger file) andmjs-cjs/ts-parser
(similar benchmark) do not have the same situation.I recently found that when I merged #16964, the situation of 1+1>2 appeared again, and the above issue disappeared.
This is confusing to me, because in my assumption the performance regression comes from recreating part of the
NodePath
(since there is no global cache anymore, when a node is moved to its parent, all relatedNodePath
need to be recreated), and that PR just avoids multiple traversals and shouldn't fix it. (Traversals are faster, so the impact of the changes in #16964 in this PR should be less than 3%)Note: This PR may be risky to merge in Babel 7, but since it doesn't require any changes to our plugins, it might be worth a try.
with #16964
without #16964