08-04-2026 04:45 AM
Generalizing Altenbachs idea got me down to 40ms!
08-04-2026 09:33 AM
The speed is still data-dependent and only wins because a large percentage of items have identical color. If each tag has roughly equal probability., it would still be better to only update the visible items at each scroll operation as has been suggested.
08-04-2026 11:45 AM - edited 08-04-2026 11:47 AM
@altenbach wrote:
The speed is still data-dependent and only wins because a large percentage of items have identical color. If each tag has roughly equal probability., it would still be better to only update the visible items at each scroll operation as has been suggested.
It looks like I have one more step forward before the end of the workday. Yes, the real problem is memory issue, and more specifically, the massive number of page faults in the "Slow" version.
Memory on Windows is organized into pages (4 KB each). When memory is accessed and the corresponding page is not yet mapped into the process address space, a page fault occurs. The operating system then maps the page, making it available to the process. However, if allocations and deallocations are performed too aggressively, this can introduce significant overhead. There is nothing inherently wrong with a page fault on the first access to a memory page, but once memory has been allocated, we should avoid excessive reallocations. This is a fundamental principle of efficient memory management.
To prove this, I prepared two stripped-down applications: one "Slow" version and one "Fast" version. The only difference between them is the surrounding sequence structure on color constant. To eliminate the impact of the outer `while` loop, I adjusted the number of iterations in the inner `for` loops so that both VIs run at approximately the same speed on my PC (about 1:20 proportion on my Xeon), on the left side is "Slow" version, on the right — "Fast":
I then built both applications and ran them side by side while monitoring them with Process Explorer. Just take a look at this:
As you can see, both applications have around 50,000 page faults at launch, which is more or less OK for a 140 MB working set. However, once running, the "Fast" version generates only about 80 page faults per second, while the "Slow" version generates more than 4,000 page faults per second. That is the real problem.
Next, I ran the application under API Monitor. Indeed, there are massive numbers of HeapAlloc and HeapFree calls:
These allocations also introduce additional memory-related penalties due to cache misses. Take a look at the LLC (Last Level Cache) statistics. The slow version experiences more than 3 million LLC misses within one minute, while the fast version has really zero after one minute:
In my opinion, this is more than sufficient evidence for NI to open a CAR. I can investigate further, but that would likely lead me into the LabVIEW Runtime internals, which I would prefer to avoid.