Open Lucretiel opened 4 years ago
Here's the complete HTML report triggering this issue: cargo-timing.html.zip
Transferred to the cargo repo.
Set the scale slider to the far left and reload the page, and then slowly raise the scale slider up to whatever limit it can handle. The problem is that the canvas is too large. AFAIK, there isn't a way to get the maximum canvas size (I think it may be graphics-card dependent), so it's kinda hard to know how to handle that.
Thanks, will give it a try
Yeah, that fixes it. Sliding the scale down doesn't do anything immediately, but refreshing afterwards does show the graphs.
I looked into this issue a bit. For me the rendering works until scale level 18, where canvas size being 4,876 x 25,406 = 123,879,656, and at scale level 19, where canvas size is 5,138 x 25,406 = 130,536,028, it stops rendering.
This is indeed a huge canvas, but not too crazy, and it's still smaller than what's documented on MDN that Firefox supports up to 472,907,776 px of area.
So I dug into Firefox source code a bit, and I believe this is not limited by something graphics card dependent, but a fixed value in the prefs, specifically gfx.max-alloc-size
, which has a default value of 500,000,000 and its unit is bytes.
It can be seen that
to confirm that, I tried changing this value to 600,000,000 and restarted Firefox (as this value is read only once at startup), and indeed I could now get to scale level 21, where the canvas is 5,662 x 25,406, and failed again at level 22, where the canvas is 5,924 x 25,406. Repeat the computation above:
So it can be seen, this pref is the limiting factor.
Currently, the code that Cargo generates seems to try to limit the width of the graph in order to ensure that it can be rendered: https://github.com/rust-lang/cargo/blob/5ccea519d43d09c0edf4b5dffc32e068fbf46296/src/cargo/core/compiler/timings.js#L297-L301
given that browsers have limitation on total area in addition to max single dimension, it might be better to limit it based on some area estimation rather than a hardcoded width limit.
Also, at this large canvas size, many browsers may have lost the graphics acceleration anyway, making the rendering very slow. I would suggest to have a canvas size relative to the viewport, and do windowing manually, rather than stressing browsers on their limits.
For me the problem seems to have to do with the height of the canvas being more than 32k pixels. The graph won’t render until I filter out enough crates with the "min duration" slider. Here's the relevant bugzilla: https://bugzilla.mozilla.org/show_bug.cgi?id=1282074
I don’t think this can be fixed holistically by cosmetic changes to the canvas-based code. Rewriting the entire thing to DOM, SVG or if canvas must be kept, implementing some sort of scrolling and a rendering loop will be necessary.
I'm also in favor of a DOM/SVG based solution, it offers several immediate benefits:
prefers-color-scheme
media query for a simple dark theme or with browser extensions There are existing tools that use both approaches, for example FlameGraph uses an SVG and speedscope uses an interactive canvas interface. I think making use of an existing tool, by either utilizing an existing benchmark file format or embedding the viewer it in the generated html would provide the best experience, but either way would probably be as much work as rewriting the entire thing...
When I run
cargo +nightly -Z timings
, it produces a timings report in HTML as expected. This renders correctly in Chrome and Safari. However, in Firefox, I only see the summary table and timings breakdown table. I can see the controls for the graph, but the graph itself doesn't render:In the error console, I see the following uncaught exception:
This exception is being thrown from the following function, specifically at
ctx.scale(dpr, dpr)
near the end:Digging into the debugger, there don't seem to be any obvious issue with that line of code.
ctx
is of prototypeCanvasRenderingContext2DPrototype
, and thescale
method has been supported in firefox pretty much forever.dpr == 2
.Meta
rustc --version --verbose
: