spiermar / d3-flame-graph

A D3.js plugin that produces flame graphs from hierarchical data.
Apache License 2.0
891 stars 119 forks source link

Efficiently update single nodes or node attributes #226

Open LinqLover opened 1 year ago

LinqLover commented 1 year ago

Is your feature request related to a problem? Please describe. I am building an interactive application that contains a flamegraph and based on the selection of other objects on the screen, I highlight the corresponding nodes in the flamegraph. At the moment, this requires me to call update() on the flamegraph to make it recolor the nodes. Unfortunately, this is pretty slow because all nodes are built from scratch, the SVG is updated, and so on. For my particular use case, it would not even be required to recolor all nodes but only two (the old selection and the new one). Analogously to changing the node's color, I also change their labels occasionally.

Describe the solution you'd like A way for efficient updates of single nodes or node attributes. Personally, I only need this for colors and optionally labels, but maybe such a mechanism would be interesting for other attributes as well. Some possible interfaces for that could look like this:

flamegraph.updateInPlace([node1, node2])
flamegraph.updateInPlace(['color'])
flamegraph.updateInPlace([node1, node2], ['color', 'label'])

Alternatively, I would also be open to a reactive approach, e.g.:

node1.emit('color')
node2.emit('label')

But I assume that such a programming style is not typical for d3.js.

Describe alternatives you've considered At the moment I always do a full update and this reduces my frame rate to <10 for small datasets. I considered speaking directly to the nodes in question but a) this feels like a terrible hack and b) d3-flame-graph apparently does not expose the actual data so I would have to search them (or build an index of them) from the SVG tree.

Additional context None, just thanks for this useful package! :-)

LinqLover commented 1 year ago

I ended up with manually accessing the nodes using d3-select like this:

https://github.com/LinqLover/trace4d/blob/1e25146bda2c2f43163440519e00a4f9349cf2d5/packages/frontend/src/player.js#L376-L387

Feels not ideal since I have to sync two different interfaces for expressing the same, but it works very efficiently!