clinicjs / node-clinic

Clinic.js diagnoses your Node.js performance issues
https://clinicjs.org
MIT License
5.68k stars 126 forks source link

Help the user see where the line is interpolated due to missing/delayed data #407

Open AlanSl opened 6 years ago

AlanSl commented 6 years ago

This is something I've already implemented on my side because I find it useful for understanding the data. If we like the idea, it's ready to PR.

Our plots are unusual compared to other time series charts and various other profiling tools because the plotting along the x-axis is (by design) not consistent - when there's no event loop delay, we plot every poll interval (10ms), then when there are delays, the resolution goes down to whatever the delays are. Within one plot there could be areas where the data is extremely fine and areas where it's extremely coarse.

Visually, there's currently no difference between a time period where we have have fine enough data to know a variable follows a consistent linear trend, and a time period where we have missing data and we're just interpolating between two data points either side of an event loop delay. Users can learn to distinguish the two, by running the mouse along and seeing where the hover box jumps or by comparing to the event loop chart (which might be off screen), but it'd help if they could just see it.

Of course, we don't want to make the UI visually busy. It needs to be unobtrusive.

This edit essentially adds a subtle highlight to each actual datapoint, making a linear trend subtly but noticeably stronger than an interpolation, and making the individual data points within a coarser delayed area easy to see.

Example with node-clinic-examples/slow-gc :

image

Example with node-clinic-examples/slow-event-loop :

image

AlanSl commented 6 years ago

I've added a branch with this: https://github.com/nearform/node-clinic-doctor/tree/highlight-datapoints

mcollina commented 6 years ago

Seems like a good idea.

AlanSl commented 6 years ago

I've merged https://github.com/nearform/node-clinic-doctor/pull/62 into this branch so we can see how it looks with step interpolation. They go well together, here's a slow event loop example where it enables the user to see where each event loop delay starts and ends through the long stretch where the line otherwise is simply high and flat:

image

slow-gc example:

image

AlanSl commented 6 years ago

I've made some slight design tweaks after testing it on a low-end, low pixel density screen (our target audience will include some developers stuck using cheap company-provided monitors). Dash arrays below <1px actually seem to be clearer on such screens (I'd expected the opposite to be true) which is nice because it also means tight angles on dashed lines are clearer.

image

AndreasMadsen commented 6 years ago

@AlanSl How is this implemented? I'm worried about performance if it is 1000+ circle elements.

Also, when the dots are really tight, it might hide the gaps we use in Memory Usage.


I'm like the idea. I'm just worried about the implementation of it.

AlanSl commented 6 years ago

re. gaps, do you mean the gaps in the stroke-dasharray to discriminate the lines? If so that's what I've been testing, see screenshots. The latest screenshot has almost no event loop delays so it's almost covered in dots - the reduced opacity and the blend mode keeps the pattern visible.

AlanSl commented 6 years ago

re. performance: Performance for high numbers of static D3/SVG elements is generally very good in Chrome so long as they're grouped and interacted with as a group. I've tested on a slow machine (10+ year old laptop) for a profile giving >1100 dots per line and it's still fast to load (<2s total page load). No impact after page load.

We might get noticeable page load delays for very long profiles (like over a minute) but until we implement zoom, the UI is near-unusable for such long profiles anyway.

Here's a comparison on a mid-range 2014 machine for a worse-case scenario with >1100 dots per line. With and without:

With: Without:

So there is a hit, but it's not at a scale that harms UX until we have profiles so big they already have bad UX.

AlanSl commented 6 years ago

This gives me an idea though - most of the hit is coming from those stretches where there's 0 event loop delay, where the many dots are visually (and conceptually) indistinguishable from a line anyway. These stretches are the ones most likely to cause performance issues if we do run into them, and that could be avoided by drawing stretches containing no event loop delay as one line instead of hundreds of dots, within the same group. Possibly premature optimisation but shouldn't be hard to implement.

--Edit: Better still, have just one element for each line, set as a compound path with stroke-linecap set to round. Could be as simple to implement as using M instead of L in the path definition for each datapoint where the event loop is frozen. Then we're only adding one DOM element per line.

AndreasMadsen commented 6 years ago

Performance for high numbers of static D3/SVG elements is generally very good in Chrome so long as they're grouped and interacted with as a group.

Yes. But that won't be the case for when the window is resized.

BridgeAR commented 6 years ago

What is the status here?

AlanSl commented 6 years ago

It's a low priority item on my to do list, most of the work is done it just needs updating and checking the perf impact is minimal.

Since it involves visualising events alongside data series it should probably be done at the same time as https://github.com/nearform/node-clinic-doctor/issues/46 (visualize GC events) so that the approaches don't clash.