Skip to content

Parallel coordinates chart - design #1071

Closed
@monfera

Description

@monfera

image

Approach

This issue is dedicated to parallel coordinates. As this is the first new chart where we're moving away from past gl-vis/***2d charts, some of the discussions is broader than that.

As we discussed on the requirements meeting, it's not easy to have both full, continuous interactivity and a lot of lines, because of the large number of lines (1k and up) either overload the shaders (no matter if WebGL or Canvas2d) or there's a need for time-consuming preprocessing e.g. splatting (we might be able to do on-GPU splatting but probably it's best to start with something simple, reasonably fast and direct).

So our requirements analysis said that - esp. with more than 1k lines - the axis sliders would be debounced, and would only render when the user stops for a bit or releases it. Even with this, a direct rendering is only good till about 10k..20k lines (around 100ms to generate) and beyond that, the direct approach would need incremental rendering. So here's an approach under consideration:

  1. Unlike with many current charts, we should avoid the rerender on every frame (useful irrespective of chart type, because it minimizes processing load) - and similarly, we should avoid "dummy renders", when a chart is getting initialized by rendering it with empty data, to be followed up by subsequent updates with more and more of the necessary input
  2. As a consequence, the line bundle (here shown as 16k blue lines) and the interactive stuff (tooltip, axis slider etc) should reside on separate layers (can be WebGL + SVG, WebGL + Canvas2d, WebGL + WebGL irrelevant for this point)
  3. We may need more layers, e.g. for some kind of a backdrop
  4. This means that the blue line bundle can be rendered with whatever is fastest (Canvas2D or WebGL)
  5. Here's the weird part 🔥 : on low-end hardware (13" Retina Macbook Pro) perf tests show Canvas2d to be faster for interesting cases (with this example, 100ms vs 500ms render time) - and I tried a couple ways of rendering lines in WebGL (though no splatting yet). Canvas2d uses hardware acceleration i.e. the GPU, and probably a lot of work went into optimizing it. On powerful GPUs the bottlenecks are probably elsewhere though.
  6. This 16k line image above is now generated with WebGL (regl) or Canvas2d, it looks almost identical (minuscule blending hue difference)
  7. Canvas2d is lightweight in that there's no additional code dependency, i.e. there's no significant bundle size increase if we use it; also, it's much quicker to prototype and do exploratory coding with Canvas2d than with WebGL
  8. As a consequence, it looks simplest to do layers in Canvas2d and/or SVG, and at some more mature stage (still within this PR) plug in WebGL (via regl) for the heavy-lifting layer to see if it does better or worse - this way we don't end up with the rather large code differences between non-WebGL and WebGL versions
  9. Therefore the calculations should be substrate independent; loose coupling between the viewModel and the renderer
  10. Since WebGL, and the eventual need for Web Workers suggests typed arrays, the parcoords proto-prototype uses typed arrays internally; Canvas2d/SVG can use it too; we can preface it with an untyped -> typed conversion for users
  11. Since typed arrays are 1-dimensional arrays but in reality encode multiple dimensions, the parcoords prototype is using ndarray - it's already part of our dependency stack so no code increase, and perf profiling shows essentially no speed cost relative to indexing manually. It makes the code a lot more readable.
  12. In conclusion, the experiences point to a code structure with a linear flow of data (also in line with current plotly.js practices):
    • user input
    • arrive at defaults
    • calculate a common viewModel
    • populate and render multiple layers, which may be of a heterogenous type, some of them alternatives to one another, and some of them getting new versions as part of shorter iterations (e.g. an SVG or Canvas2d layer gets a WebGL / regl alternative)

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions