-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
Incremental Symbol Propagation #8723
Conversation
5606d3c
to
f9e47dd
Compare
Benchmark ResultsKitchen Sink ✅
Timings
Cold BundlesNo bundle changes detected. Cached BundlesNo bundle changes detected. React HackerNews ✅
Timings
Cold Bundles
Cached Bundles
AtlasKit Editor ✅
Timings
Cold Bundles
Cached Bundles
Three.js ✅
Timings
Cold BundlesNo bundle changes detected. Cached BundlesNo bundle changes detected. |
3f2252e
to
c441fd2
Compare
Excited for this. Sort of hard to see the diff of what changed since it moved to a new file, but we can test it out on some apps. Any performance numbers you've seen so far? |
packages/core/utils/src/hash.js
Outdated
let testCache: {|[string]: Promise<string>|} = { | ||
/*:: ...null */ | ||
}; | ||
export function hashFile(fs: FileSystem, filePath: string): Promise<string> { | ||
if (process.env.PARCEL_BUILD_ENV === 'test') { | ||
// Development builds of these native modules are especially slow and slow to hash. | ||
if ( | ||
/parcel-swc\.[^\\/]+\.node$|lightningcss.[^\\/]+.node$/.test(filePath) | ||
) { | ||
let cacheEntry = testCache[filePath]; | ||
if (cacheEntry) return cacheEntry; | ||
let v = hashStream(fs.createReadStream(filePath)); | ||
testCache[filePath] = v; | ||
return v; | ||
} | ||
} |
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.
(This is the workaround to speedup the integration tests)
I've moved the code back (be sure to hide whitespace changes!), will do that again in a separate follow up PR.
Testing with ak-editor (on initial builds, both passes were ~200ms each before):
I haven't tested the case where a large dependency is added. |
a8e6e10
to
812bce3
Compare
aebbf04
to
792aee9
Compare
792aee9
to
4b47954
Compare
ff2873f
to
2a72bb5
Compare
2a72bb5
to
166a043
Compare
@@ -747,110 +889,150 @@ export class AssetGraphBuilder { | |||
} else if (childNode.type === 'dependency') { | |||
childDirty = childNode.usedSymbolsDownDirty; | |||
} | |||
if (!visited.has(child) || childDirty) { | |||
if (childDirty) { |
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.
Does this mean nodes may be visited more than once now?
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.
Unfortunately yes, I've added another comment:
parcel/packages/core/core/src/requests/AssetGraphRequest.js
Lines 846 to 863 in d7d0d01
// In the worst case, some nodes have to be revisited because we don't want to sort the assets | |
// into topological order. For example in a diamond graph where the join point is visited twice | |
// via each parent (the numbers signifiying the order of re/visiting, `...` being unvisited). | |
// However, this only continues as long as there are changes in the used symbols that influence | |
// child nodes. | |
// | |
// | | |
// ... | |
// / \ | |
// 1 4 | |
// \ / | |
// 2+5 | |
// | | |
// 3+6 | |
// | | |
// ... | |
// | | |
// |
(But the hope is that this won't happen often. If it does become a problem, then we should tweak the traversal order)
Hide whitespace changes when viewing the diff
This removes the previous two unconditional graph traversals (which in many cases didn't do anything because there were no changes) and instead runs the symbol propagation starting from changes (so
changedAssets
anddependenciesWithRemovedParents
, which isn't covered by changedAssets).(If more than 50% of the assets changed, it uses the old full top-down traversal approach in one case, to prevent some revisiting. This 50% threshold was arbitrary, not sure if it's too high or low.)
Additionally:
does not export
errors in development*
symbol to assets without exports (just like with scope-hoisting)*
symbol to dynamic import dependenciesassetNode.value
for changed assets, as opposed to the whole node (which also contains the asset's used symbols)Followup tasks:
import * as x
isn't analyzed in dev mode, so there are no CSS module symbol import errors