ImPlot: Interactive plotting library, ImGui style
github.com
github.com
I work with a lot of assembly traces emitted from CPU sims in Verilator. These traces can be several gigabytes in size, with tens of millions of entries. I've found the typical interactive matplotlib backends to not work the best with tens of millions of points on my M1 Macbook Pro. This is no slight against Matplotlib, or cairo, or agg, or the default macOS backend—they prioritize cross-platform "It Just Works" support over extreme performance.
But it does irk me that there seems to be such a gap between the amount of data we can visualize in the gaming domain in comparison to the scientific domain[1]. The difference between 50 million and 5 billion is 100X. I'd be ecstatic if I could get within 10X difference. I understand that this gap exists for lots of reasons, of which I'd be happy to hear in detail in the replies to this comment.
In a video game it's easy to figure out what not to show - just hide everything that would normally be too small or far away to see. But in a scientific domain, what to show and what to hide might be a much more interesting question.
On the other hand, if you're just looking for a plot of a few billion elements with the ability to zoom in and out, then a straightforward decimation of the data and drawing it to the screen can work. In the past I've written custom tools to do just that, but at this point in life I would probably throw it at something like SciChart and let it take care of that.
The actual implementations of 3D rendering are gargantuan feats of engineering, science, and art. Having spent time writing code to turn terrain height maps into quantized meshes for 3D rendering, I agree entirely that deciding which vertices are important is not a trivial problem. The OP linked a video about Nanite, which IMHO is a marvel of engineering.
For graphics, the main performance metric is (generally) triangle count. You can draw lots of low-poly objects on screen more efficiently than you can draw one very high-poly object. The same holds true for data: you can render low amounts data more efficiently than you can render large amounts of data. Nanite doesn’t magically render high-poly meshes in real time. Nanite needs to pre-process the mesh and produces lower poly meshes that maintain the geometric properties of the original mesh. This is the main innovation of nanite, because traditionally it’s been very hard to reduce triangle count while keeping the overall geometry roughly similar to the original. And in this way, data processing has traditionally been much more efficient than 3D graphics. There have long been various statistical aggregations you can do on data to keep the same rough statistical properties using less data. But you have to be willing to preprocess the data, and that is slow. I haven’t used nanite, but I imagine the import process is also slow relative to the rendering speed after processing.
depends on the data/graphics. modern commercial GPUs are beefy (even when talking about integrated ones) and I suspect the Matlib kinds of tools aren't even tapping into a fraction of a percent of its power.
But at the same time 5 billion draw calls raw will bring even a decent gaming GPU to its knees, at least for responsive, real time applications. The trick is to first understand your data (e.g. that 5 billion triangles are useless on a monitor that has 1-4 billion pixels). As you said, even Nanite isn't truly trying to process a trillion triangles raw.
The steps from that understanding to a good enough approximation are indeed some dark magic.
At various zoom level what you actually want is a low pass filter over a slice of the data, such that the low pass filter matches the display. E.g. I can display 1080 pixels across, but there's 1 billion points. Ok... meaningful data is limited.
Optionally you could do what other device displays do and show a sort of fuzzy intensity gradient at each display x axis over y points to represent the number of actual samples at that point.
It's kind of crazy honestly. There's many options to display billions of points across 1080 pixel wide displays but none of them really show you the reality. Only some subset of information of the reality there.
For reference, the newest Zelda game is a total of 18.2GB of storage, and of course Zelda isn't trying to audit the entire game on every load. Games spend a lot of time making sure their assets are lean, and at the end it is deployed in some binary format to further reduce its impact on a game. trace files that focus on human readability lose this compressibility.
So regardless of how fast the graphical plotting capabilities are, I imagine such an app is CPU bound from simply trying to parse that trace data. That'd be the first place I'd look to optimize (you know, without properly profiling your app. Probably something I'd say in an interview setting).
Gaming is highly specialized applications, so you should also be comparing to highly specialized applications in scientific domain.
I'm not sure I fully understand why some projects so proudly avoid using standard library features and e.g. favour a more manual approach to memory/data management. What are some good key reasons for this?
> avoids ... C++ headers
Same question for this point - but is it the same reason as for avoiding STL containers or something else?
C++ is a big language and there is a lot of diversity of opinion in what a sensible subset of the language is, with numerous concerns influencing those decisions -- one common one is compile times. Using C only headers generally ensures a much lower ceiling for compile times compared to using typical C++ headers. And C++ headers are slightly more likely to use the prolific allocation strategy from above. As such, C++ headers require far more scrutiny before acceptance, in my view.
> Same question for this point - but is it the same reason as for avoiding STL containers or something else?
ABI compatibility and the ability to easily create FFIs for other languages are the strongest appeals afaik.
Same for headers, compile times matter. I'm very much looking forward to widespread, fully-modulized standard libraries.
Also, it's not like writing your own growable array is rocket science, and a simple, specialized version can be done in a few dozen to a few hundred lines of code.
One reason STL was avoided is that control over memory allocation was quite poor. std::allocator was somewhat conceptually broken for a long time, only recently remedied in C++14 and 17. So, there's still about 20 years of code out there from the days of old bad C++ (:
Another reason is that early STL implementations were poor, and not well-suited to high-performance use cases. Again, this has gotten better (some), but the legacy lives on.
Here's a good one to read: https://github.com/electronicarts/EASTL/blob/master/doc/Desi...
So, if you are designing a library to be used in video games (such as in TFA), and want wide adoption, then avoiding STL, RAII, exceptions is still generally a good idea, IMO.
As soon as you need to support multi-line text or Unicode text, you will run into a hard wall fast.
Oh and accessibility. No accessibility.
There are other issues too, but these two are typically deal breakers for any serious (or even hobby) application with a non-trivial UI.
Some prior discussion: https://news.ycombinator.com/item?id=24987964
That's great for bootstrapping, not great for scalability.
> The only other UI framework I know of that is comparably simple is html and css
I'm curious to hear more. What's an example where the HTML/CSS is simpler than putting together something similar in another UI architecture?
Compared to, say, XAML, where some elements can only have certain types of children, auto-populating data has to go in specific containers, and all the XAML tags map to actual C# classes, It's a much more strict, far less forgiving, and far less flexible syntax
Screenshot: https://i.imgur.com/8Mc04NB.png
Repository: https://github.com/UniStuttgart-INS/INSTINCT
D3, Domo, Highcharts, Tableau, or dozens of other charting and dashboarding options?
Screenshot of a program that uses this library: https://fdkz.net/static/images/20171215-aniplot.png
Screenshot: https://cloud.githubusercontent.com/assets/77752/5382993/9f6...
Turns out, not really. It's very easy to make performance worse like this. I'm sure you can find scenarios where it makes sense, but in general it's just not a big deal.
This can work out as a net positive, because copying memory can be cheap compared to recalculating the data it contains. But if your API requires the caller to resubmit all the data on every frame, it makes no difference.
(Which is not to suggest there's anything wrong with requiring the caller to resubmit all the data, if it makes life easier for them. The worst case needs to perform well and one way of making sure it does is to make sure it's exercised all the time.)