Edda
Edda copied to clipboard
Paginate drawing of editor grid
Currently we draw the entire editing grid (waveform, grid lines, notes, markers) all at once. This will cause performance issues for very large (>> 10 min) maps.
A better solution would be to draw the grid in chunks depending on the part that's currently being viewed.
- how far ahead/behind the current seek point do we draw?
- how should we handle redraws while the song is playing?
- what happens if the user jumps to a completely different point on the grid? will there be lag?
- we need to implement debouncing for the redraw function so the program doesn't explode when the user seeks rapidly.
I've profiled the code recently for longer songs and found that this significant performance issues do not come from the rendering (GPU usage is still below 1%), but more from the Control.Layout event that is triggered for all children when ScrollViewer changes position. This is typically remedied using UI Virtualization on the container, but Canvas doesn't support it.
I've found this implementation of a custom VirtualCanvas. I'll test it when I'll have some free time to see how much it will help.
that's interesting (and a bit weird). did you just use the visual studio profiling tools for that?
Profiling was done using Visual Studio Fools, yes.
I've also looked at Windows Resource Monitor while playing the songs and saw that while it was lagging, GPU was hardly being used, CPU was basically the same as when idle and memory only reached 4 GB at peak - I'd expect one of those to be used to capacity (as with e.g. Spectrogram - there CPU goes to capacity while analyzing the samples), but that was not the case.
it's definitely an issue concerning the CPU.
FFTs are optimised very well for processors so the spectrogram will happily use up as many CPU resources as allowed, but with something higher level like .NET and WPF frameworks it's a bit more dubious as to what actually performs well.
there are a few things I can think of that might be contributing to the problem.
- audio playback and latency is tuned quite aggressively which puts a bit of strain on the CPU, particularly in terms of single thread performance.
- WPF rendering is single threaded, so there are cross-thread communications going on which might incur large overheads.
Unfortunately I got stuck with my tests to check if the VirtualCanvas I've mentioned would help the performance by providing UI virtualization.
The implementation would require using an ItemsControl with a bindable collection of canvas elements that supports dynamic realization of elements in a given Rect, but I'm stuck at the first step, trying to just refactor the existing Canvas in a ScrollViewer into an ItemsControl - something happens to the ScrollViewer and the scrolling stops working altogether, and I have no idea why.
I'm afraid I don't have enough free time nowadays to keep trying to get this to work, especially since I'm not 100% sure it would help that much, as you pointed out.