-
Notifications
You must be signed in to change notification settings - Fork 322
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
Faster dev builds; tooling for measuring build times and app performance. #3491
Conversation
…mance. - Change debug profile settings to avoid generating multiple GB of debug data that wasm-pack discards anyway; improves build performance, especially for mid-to-large incremental changes. - Introduce script for benchmarking various incremental builds. - Add a line to `intervals` showing total main-thread CPU work logged in a profile; this can be used to compare the results of optimizations.
@wdanilo Re: our call this morning, I just compared |
Thanks for the info! I'm not sure if we should not do it though. If you are working on a visual component, any speedup is important. After pressing save, waiting 9 instead of 10 seconds is a small, but observable difference. If you are modifying colors and changing padding, you're compiling GUI hundreds of times per day and this makes the process more smooth. If this is one-shot job (defining the build mode) I think we should just do it in order to optimize these builds for the interactive development as much as possible. What do you think of it? |
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 amazing.
@kazcw |
Re: @mwu-tow Re: @wdanilo |
Ah, it is far less troublesome then. I have no issue with this.
I don't think that this would work, AFAIR |
Wow, I can't believe they don't support that. Tomorrow I will look into a workaround. |
@mwu-tow
|
@kazcw Perhaps we should then just add additional parameter for "rust debug level"? Then we'd able to adjust it for all wasm-pack profiles. |
@mwu-tow That works. |
Because I put the new build benchmarking script in the |
Add the people who havn been involved in the development of those areas
I don't know the plan for |
…file. (#3498) ### Pull Request Description Using the new tooling (#3491), I investigated the **performance / compile-time tradeoff** of different codegen options for release mode builds. By scripting the testing procedure, I was able to explore many possible combinations of options, which is important because their interactions (on both application performance and build time) are complex. I found **two candidate profiles** that offer specific advantages over the current `release` settings (`baseline`): - `thin16`: Supports incremental compiles in 1/3 the time of `baseline` in common cases. Application runs about 2% slower than `baseline`. - `fat1-O4`: Application performs 13% better than `baseline`. Compile time is almost 3x `baseline`, and non-incremental. (See key in first chart for the settings defining these profiles.) We can build faster or run faster, though not in the same build. Because the effect sizes are large enough to be impactful to developer and user experience, respectively, I think we should consider having it both ways. We could **split the `release` profile** into two profiles to serve different purposes: - `release`: A profile that supports fast developer iteration, while offering realistic performance. - `production`: A maximally-optimized profile, for nightly builds and actual releases. Since `wasm-pack` doesn't currently support custom profiles (rustwasm/wasm-pack#1111), we can't use a Cargo profile for `production`; however, we can implement our own profile by overriding rustc flags. ### Performance details ![perf](https://user-images.githubusercontent.com/1047859/170788530-ab6d7910-5253-4a2b-b432-8bfa0b4735ba.png) As you can see, `thin16` is slightly slower than `baseline`; `fat1-O4` is dramatically faster. <details> <summary>Methodology (click to show)</summary> I developed a procedure for benchmarking "whole application" performance, using the new "open project" workflow (which opens the IDE and loads a complex project), and some statistical analysis to account for variance. To gather this data: Build the application with profiling: `./run.sh ide build --profiling-level=debug` Run the `open_project` workflow repeatedly: `for i in $(seq 0 9); do dist/ide/linux-unpacked/enso --entry-point profile --workflow open_project --save-profile open_project_thin16_${i}.json; done` For each profile recorded, take the new `total_self_time` output of the `intervals` tool; gather into CSV: `echo $(for i in $(seq 0 9); do target/rust/debug/intervals < open_project_thin16_${i}.json | tail -n1 | awk '{print $2}'; do` (Note that the output of intervals should not be considered stable; this command may need modification in the future. Eventually it would be nice to support formatted outputs...) The data is ready to graph. I used the `boxplot` method of the [seaborn](https://seaborn.pydata.org/index.html) package, in order to show the distribution of data. </details> #### Build times ![thin16](https://user-images.githubusercontent.com/1047859/170788539-1578e41b-bc30-4f30-9b71-0b0181322fa5.png) In the case of changing a file in `enso-prelude`, with the current `baseline` settings rebuilding takes over 3 minutes. With the `thin16` settings, the same rebuild completes in 40 seconds. (To gather this data on different hardware or in the future, just run the new `bench-build.sh` script for each case to be measured.)
Pull Request Description
intervals
showing total main-thread CPU work logged in a profile; this can be used to compare the results of optimizations (I'll be starting a discussion informed by that data separately; this change just enables the tooling to report it).Dev profile settings
Let's start with a before-and-after. Here are the dev-mode build times for various incremental changes (data collected with the new
bench-build.sh
), without and with this PR:The impact is greatest for far-reaching incremental changes--rebuild after editing a file in
enso-prelude
now takes less than half the time.The fix: more debug info is not better
I noticed that the file
enso_gui.wasm
, which is the output of Rust compilation and the input ofwasm-pack
andwasm-bindgen
, was 3.3 GB. Since theide.wasm
file produced bywasm-pack
is about 80 MB and is not compressed, I suspected rustc was putting data in there that wasn't being used.wasm-objdump
revealed that the file consisted almost entirely of debug info. The problem turned out to be a setting in the workspace'sCargo.toml
: for thedev
profile, we had a setting to enable debug info:debug = true
. As it turns out,debug = true
enables extremely verbose debug info thatwasm-pack
can't use (much of it is not usually used by anything even on x86); the subtly different settingdebug = 1
enables enough debug info for informative stack traces, which is all we need debug info for, and it does it with gigabytes less compiler output.Could the extra information ever be useful?
It's possible that some day,
wasm-pack
will support emitting this data inwasm
files, and DevTools will support using it; but WASM doesn't even support encoding this information yet, so let's revisit this in the future when the tooling supports it.Why does the rustwasm book recommend
debug=true
?Good question. Let's see if they know about some reason for it.
Checklist
Please include the following checklist in your PR:
Scala,
Java,
and
Rust
style guides.
./run.sh ide dist
and./run.sh ide watch
.[ci no changelog needed]