perf(linker): Fixes brute force chunk cycle detection #3069
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #3068
Approach
Given that the behavior is concerned only on detecting a cycle rather than identifying them, the simplest possible revision would be to improve current approach's shortcomings. Practically, this would mean
I used an approach borrowed from topological sorting, in which nodes are marked with a state (not-visited, visiting and visited), and if they've already been visited, we skip them. Furthermore, if we find a cycle, we halt. That gives us a linear execution time, rather than exponential.
Results and reproducibility
It's clear that the impact of this would only be seen on some areas of the input space. Particularly, past a given graph complexity. Consuming the change from this fork, the vendor build which was taking up to ~400s, dropped to 4s, a 100x (anecdotal) improvement. The app build's incremental times dropped from ~150s to ~30s, a 5x improvement.
Since this is a plain algorithmic revision, I believe that the point could be proven with a benchmarked test, and didn't see the need to generate a sufficiently complex npm dependency graph and run a full
esbuild build
on it.Code Sandbox: https://codesandbox.io/p/sandbox/blue-http-750ebf?file=%2Flinker_test.go&selection=%5B%7B%22endColumn%22%3A6%2C%22endLineNumber%22%3A10%2C%22startColumn%22%3A6%2C%22startLineNumber%22%3A10%7D%5D