Open
Conversation
…rden fallback behavior
|
I tried this version and it works fine in local environment, decreased wiring time from 20s to roughly 1s.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
This PR overhauls the loader process for Wire which has significant performance issues under various circumstances. Most of which were tied to go/packages semantics and go/types type checking work. With larger codebases, you incur a growing cost of both as a baseline. For example, in a project that stock Google Wire would take 1.3s to run, 400-600ms of that was go list deps and the rest was type checking all external and internal packages recursively in order to do what Wire needs to do. This PR replaces the loader process, caches the heavy work and invalidates it when necessary.
Safety
Safety, accuracy is important above all else. Existing Wire tests pass along with a plethora of newly added scenario based testing.
Test it Yourself
You can test the new loader yourself by installing this branch:
Revert back to goforj
Or to stock google wire
Custom Loader
This custom loader implementation is far more consistent than previous cache attempts (on goforj/wire) where those cache attempts were tackling the issue further down the line when they needed to be addressed more upstream in the loader. While this was helpful, you'd lose your compile speed under certain edit types. This implementation provides consistent lightning fast compile times across the board in many scenarios. See table below for measurements.
The table below illustrates up to 70x+ speed improvements, but these improvements scale with codebase size and complexity so you can maintain a great development experience even under massive repositories.
Benchmarks
Implementation Details
This PR replaces the primary
go/packagespath with a custom loader that is much more intentional about what work it does and when it does it.There are two different kinds of work:
By separating those layers we can skip far more repeated work than before.
Loader
Most of the new implementation lives in
internal/loader.custom.gois the main custom loading backenddiscovery.goanddiscovery_cache.gobuild and reuse the discovered graphartifact_cache.gostores typed package artifacts for reuse between runsfallback.gopreserves a safe fallback path when neededtiming.goexposes timings so we can see where time is actually goingCaching
Caching is now a first class part of generation instead of a thin optimization layered on afterward.
This is what enables the very fast
unchanged rerunandbody-only local editpaths in the benchmark table.Parser / Wire Integration
The parser and provider set handling needed to be updated to operate cleanly with cached semantic state.
internal/wire/parse.gonow reconstructs provider information from semantic artifacts when safeinternal/wire/output_cache.gowas updated around the new loader flowinternal/wire/wire.gonow drives generation through the new loading backendinternal/wire/load_debug.goandinternal/wire/loader_timing_bridge.gomake the new path observable via -timings flagOne important detail here is that the system still prefers falling back cleanly over trusting cached reconstruction when it is not safe to do so.
CLI
The command surface was updated to route through the same generation model instead of splitting behavior between commands.
wire gen,wire check,wire diff, andwire shownow run through the new backendwire watchstays on the same core generation path rather than inventing a separate implementationwire cachewas expanded so cache inspection and clearing are easiercmd/wire/main.gonow wires cache and loader behavior more explicitlyColorization There are now new colorization for errors (red) and success (green) to make things a little easier to read in between watcher tooling spam. Multiline errors are now presented more user friendly.
Compatibility / Safety
This is meant to be a conservative loader change, not a semantic rewrite of Wire. Everything works the same outside of some of the tweaks goforj/wire has made by introducing
wire cache clearwire serveThat shows up in:
internal/loader/loader_test.gointernal/wire/wire_test.gointernal/wire/parse_coverage_test.gocmd/wire/main_test.goBenchmarks
The benchmark harness was also expanded so it measures concrete developer workflows instead of only raw repo scale. (Seen in the table above)
scripts/import-benchmarks.shnow prints both scale and scenario tablesinternal/wire/import_bench_test.gonow measures edit types like unchanged reruns, body edits, shape edits, and import togglesThere are now a few benchmark profiles:
localfor a modest local graphlocal-highfor a very large local graphexternalfor a graph with a much heavier external dependency surface