This page collects some ideas about optimizing the rendering code (the main graph widget).
In the following, 'rendering' is used for 'turning visual attributes into bitmaps' and 'repainting' for copying the bitmap images of nodes in the right place to show the network. Presumably repainting is much faster than rendering. This assumption is used by many of the ideas below.
I(DanielAbel) hope that I am not mis-interpreting the behaviour of the current code in the description below.
- cacheing of rendered nodes: rendering a node, especially if it has a text label, is much slower than copying the image of the node. Thus, (for a given zoom level) rendering should be only done once, to a cached image, and when drawing the graph simply that cached image has to be copied to the right place.
- when zooming the view, instead of re-rendering everything to redraw the graph, simply scale the exsisting view and then re-render it in an idle callback. (This is what evince does, for example.) This would mean that when doing a zoom, first the view would look blocky (since a bitmap image was scaled as fast as possible) then it would clear up. In effect this allows to sacrifice (temporary) visual correctness for responsiveness.
- There is no need to re-render the graph when panning it: the previously rendered image (of the visible part of the graph) simply has to be re-painted, in a different place and only the new part (which is now visible, but wasn't visible previously) has to be rendered. For figuring out what to render in this second part, the same code that currently only renders the visible part can be used.
- When moving a node, the nodes and edges that are not moved should not be re-rendered: the stationary nodes and edges can be simply treated as background, rendered once to an image, when the move begins and only repainted from this image. Currently the repaint speed, and thus the responsiveness of the gui, is slower when a node is moved in a large network than when in a small network and there is no intrinsic reason for that.
- LOD could also depend on interaction: If rerendering is needed often despite the tricks mentioned above, (for example, rerendering of some edges when it's endpoint node is moved) the LOD could be set lower (possibly for only those objects, since for the rest, which doesn't get rerendered, this is not needed.)
- rendering should be done in background, not in the main thread (if possible): see also Matthias Reimann's mail to cyto-staff list on 2008. jul. 2.
- Bird's Eye View could be lazily updated: when doing interaction-heavy operations (i.e. moving nodes, etc.) the Bird's Eye View might be a performance bottleneck, because it has to re-draw everything (even if at low detail); (note: I haven't actually benchmarked this. ) If this is problem, it should be setup up so that during such interaction Bird's Eye View can be allowed to lag behind the main view.
- Approximate rendering: sacrificing correctness for speed The worst-case scenario for layouting / rendering is a hairball network without any discernible structure. This is also the worst-case scenario in terms of usefulness of the result. I.e. layouting and rendering will be (in general) slowest when the results are the most useless. (Nodes overlap, and the whole network looks like a giant hairball.) It might make sense to simplify the rendering in this case. For example, simply draw a cloud instead of a bunch of overlapping nodes.