-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
Experiment: Create timing report. #7311
Conversation
r? @nrc (rust_highfive has picked a reviewer for you, use r? to override) |
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.
Wanted to say first off that this is awesome to play with. I'm looking forward to iterating on this to a point where users can easily know what the bottleneck of their compilation graph is and easily diagnose performance issues.
Some miscellaneous thoughts reading your generated HTML report:
-
For Cargo, and I suspect other projects, this is a huge amount of information to take in in terms of dependencies. I wonder if we could perhaps hide most units by default? For example if things took less than 100ms they don't necessarily need to be shown (although having them optionally shown would still be good). I find the huge waterfall sort of hard to take in because there's lots of noise to sift through to find what you want, and basically either making it default or dynamically tunable to figure out what happened would be great.
-
Could the output of
rustc --version
be included in the summary? -
How come only some of the dependency edges showed up when you hover over things? In your example graph, for example,
regex-syntax
doesn't appear to unlock anything. Ah I guess it's because something else was the last thing to unlockregex-syntax
-
Printing out a "critical path" would be pretty neat for easy diagnosis.
-
Have you checked around to see if there's any sort of open formats for this sort of data? We've had success taking
perf
output and throwing it into Firefox's flame graphs on perf-html.io for example, and I think timing in the compiler has tried to use Chrome's viewer for rendering this data. Basically I'm curious if we could also massage this into an output that's usable in a viewer maintained by others which may be a bit more powerful for exploring the data after you capture a run. I'm largely just curious if we can ping the compiler team to see if this sort of data can be imported into the Chrome viewer. -
We should enable rmeta notifications for everything in
-Z timings
so we can track codegen time for all units, not just those pipelined perhaps? (or maybe document a disclaimer somewhere) -
It might be good to have a blurb in the unstable documentation about how to read the generated HTML from Cargo
-
Wow
libgit2-sys
andcc
take way too long to compile. I'm going to try to fix that.
cx.bcx | ||
.config | ||
.shell() | ||
.verbose(|c| c.status("Running", &cmd))?; | ||
self.timings.unit_start(id, self.active[&id]); |
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 for the highest fidelity of timing information we should push this unit_start
to just before the process is actually spawned on the worker thread itself (using internal synchronization in self.timings
). It's probably not worth doing that just yet though since we're already getting what appears to be pretty accurate timing information.
☔ The latest upstream changes (presumably #7216) made this pull request unmergeable. Please resolve the merge conflicts. |
a4a551e
to
cf211e0
Compare
FWIW I was curious so I was poking around with this today. I was thinking of I also read over Firefox's format and didn't dive too deep into it but figured it wouldn't work. All in all I don't think we'll get much use out of trying to use an open format. One idea I had though was inspired by this post where it'd be ideal if we could flatten this whole graph to see a more linear sequence of events rather than a huge waterfall. We could ideally say what core each process started running on and associate that with rows, so everything would be a bit more compact and you might be able to more visually see idle parts of the build. If you want to get crazy it'd be pretty sweet to overlay "what's currently building" along with CPU usage over time so we could get an idea of when the CPU is idle, what's building, and what it's bottlenecked on. To reiterate though there's tons of directions we could take it, and landing anything is better than pontificating about how we could improve it, so I'd lean on the side of landing what we have vs wondering how to implement more fancy features. |
Right, for the regex-syntax case,
What does this mean? Can you give an example of what it would say? It seems like there are many, intertwined critical paths, so I'm not sure what it would mean. Hide the units without edges? Also, some of the critical paths are just a happenstance of timing. If cargo randomly picks a different unit from the waiting set, the critical path may end up looking very different.
I looked around a little, and I didn't see anything that would be usable. If anyone has any ideas, I'd like to try them. I also considered using one of the javascript graphing libraries, but most of them didn't fit, and I wanted to avoid heavy dependencies. One thought I had was to add the JSON output and then allow other tools to process and display it. I could also move the actual HTML part of this PR to a separate repo, but I figured its utility would be severely reduced.
My original version was exactly this (it had one row per cpu). It had some drawbacks. You can't visualize how the dependency edges work (particularly for pipelining). It also ends up just being a solid block of boxes until the end when there is 1 or 2 left. I had mouseover tooltips to help show more information, but it just didn't seem that useful. The alternative I intended was the graph at the bottom tells you whether or not it is maximizing the concurrency (via the green line). But it is a bit difficult to visualize. I also had a mouseover tooltip on the graph line to show which units were currently active, but I didn't finish it and took it out to get earlier feedback on whether this is generally useful. I'm happy to continue discussing ideas for what to display and more interactive features. I just wanted to see if this is something we'd like to add at all. I'd like to focus on actionable information — that is what decisions and changes would a user make after reading this information. Seeing the graphs can be "nifty", but if it doesn't help make changes, there isn't much value. And the user does not have very many options (removing dependencies, splitting libraries into smaller pieces, removing features, etc.). |
I personally very much agree with this, and I should probably frame my comments moreso in how I think that this sort of information will be interpreted. When I personally analyze graphs like this I'm looking for a few things:
I think that the current implementation you've got here is good enough for most of these metrics above. The reason I was curious about open source tools is that exploring the current graph is pretty difficult. For example my browser (Firefox, maybe it's buggy?) gets super janky when I'm scrolling around the giant SVG. Additionally it's difficult to see what unlocked a dependency (the line drawn into it) as well as what it unlocked because the units it connects to may be either above or below the fold. These aren't really things I expect us to fix, but it'd be cool if there was an open viewer for this that already solved these problems, but I wasn't quite able to find one! FWIW I think it's also worth pointing out that the green line is an approximation of parallelism but it doesn't take into account internal parallelism in rustc (because it can't, really). That may not matter a huge amount for most projects though. Overall I'd be fine merging this basically as-is with a few small improvements in the inline comments above. It's pretty low-risk in terms of maintenance and if we ever want to remove it it's not that hard to remove. |
☔ The latest upstream changes (presumably #7351) made this pull request unmergeable. Please resolve the merge conflicts. |
Also add some more features.
cf211e0
to
0df0595
Compare
I switched to using canvas which should be faster. Let me know if it has any problems. It also allows interactive controls, and I added a few as examples. |
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.
Just a few stylistic nits, but otherwise I think this is basically ready to merge.
One thing I'd be curious to do is to overlay the "# Units" graph with CPU usage of the host system during that time (graphs like this) so we could get an idea of what the CPU usage is as well, knowing that if the number of active units doesn't shoot up you might still actually be using all the parallelism you've got locally (or not, depends). I wouldn't mind trying to whip that up after this lands though
Also I can confirm the canvas is indeed speedy, and the touch to color build script executions a different colors was nice! |
Updated with review comments. Thanks!
I'd love to see that. I was reluctant to add a dependency for this, since I suspect getting it to compile and work on all host platforms will be tricky. I also experimented with changing jobserver to report what it thinks the current concurrency is, which could be more useful with parallel-rustc. That's something we could also consider for later. |
@bors: r+ |
📌 Commit 8be10f7 has been approved by |
Experiment: Create timing report. This is just an experiment, so I'm not sure if we'll want to merge it. This adds an HTML report which gets saved to disk when the build is finished. It is primarily geared for identifying slow dependencies, and for visualizing how pipelining affects the build. Here's an example: https://ehuss.github.io/cargo-timing.html You can mouse over the blocks to highlight the reverse-dependencies that are released when a unit finishes. `syn` is a really good example. It does a few other things, like displaying a message after each unit is finished. See the docs for more information.
☀️ Test successful - checks-azure |
@ehuss the js render seems not happy with a huge project(~550 deps) |
@est31 thank you, rebuilding :) |
FYI, I know I had mentioned this before but I have an old branch laying around where I hacked cargo to output profiling info in Chrome's tracing format: There are a zillion formats for profiling/tracing info like this unfortunately. The nice thing about supporting someone else's format is that you can use other tools to explore it like Chrome's |
This is just an experiment, so I'm not sure if we'll want to merge it.
This adds an HTML report which gets saved to disk when the build is finished. It is primarily geared for identifying slow dependencies, and for visualizing how pipelining affects the build.
Here's an example: https://ehuss.github.io/cargo-timing.html
You can mouse over the blocks to highlight the reverse-dependencies that are released when a unit finishes.
syn
is a really good example.It does a few other things, like displaying a message after each unit is finished. See the docs for more information.