Big component update - slows down the other UI elements


#1

Hello everyone,

I'm currently trying to port one project of mine to Juce (a Tracker made in C#) and so far, despite my beginner level in C++, I'm getting some nice results, Juce proves really an excellent framework.

One problem I am having is that my track views, though not complex, are quite big and must all be updated at the same time. The problem is that other UI elements (such as sound-wave displayers) are sluggishly updated when the track views are.

Here is a small image to show a bit what it looks like (yes, it's ugly :).

 

Quite a lot of text, as you can see. For now the tracks are updated only on a click on a row, but there is definitely a lag in the update of the sound-wave views at the top when doing so (plus the CPU going up to 10%).

 

So my question is: what can I do to update all this big tracks at once? Maybe use some kind of background processing in a buffer that would then be dumbly copied to the visible area? If yes, how to do this?

 

Thank you.

Julien.

 


#2

Whilst it's hard to say without seeing your source code, some points to consider are (forgive me if you already know some of these, I do not know your level of experience outside of C++):

  • Make sure your'e running in release mode; there's a huge difference in performance.
  • Use a profiler to find out what parts of your code are taking the most time up.
  • Rather than try to process the information in realtime, preempt as much of the event as possible and do the processing beforehand, allowing you to just process only what's changed / display the results at the appropriate time.

Hope this helps!


#3

+1 to all of these suggestions!

ALWAYS run a profiler on your code when you hit a performance issue - it'll almost always show up some surprises.


#4

Thanks a lot for your replies.

  • I tested in Release mode before posting. It was indeed much better, but the lag was still noticeable.
  • There is only minimal processing. The data are straightforwardly read and only some String concatenations are performed.
  • I'm not very familiar with profiling with C++, but I did it with Very Sleepy and it shows quite clearly that most of the time is spent in the "paint" method of the Component where one line is written. I tried writing raw Strings instead of building them (just to see if getting my information was costly), and it doesn't change anything. So my conclusion is that it's really the text writting that takes all the CPU.

One obvious optimization would be for each snippet of text to keep the last sentence it wrote, and only write it again if it is different. However, it won't happen often with real data (but it's worth trying).

 

Now, some questions if I may:

  • Is there a way to have one component being drawn more lazily than others? For example the waves display at the top could be more prioritized compared to the tracks below.
  • Is there a way to optimize the text display (maybe by making it less aliased)?
  • Would displaying pictures instead of text would be significantly faster (one picture per letter, generated on font size change for example)?
  • Is the change of colour and getFont expensive? They don't weight much in the profiler, but maybe have heavier consequences than what it shows.

Thanks,

Julien.

 

 


#5

Is there a way to have one component being drawn more lazily than others? For example the waves display at the top could be more prioritized compared to the tracks below.

Yes, you could do this. However, it seems that you'd be avoiding the real performance bottleneck rather than solving it ;)

Is there a way to optimize the text display (maybe by making it less aliased)?

Do you mean "can I disable anti aliasing" or something else? IIRC, the text is already anti aliased.

Would displaying pictures instead of text would be significantly faster (one picture per letter, generated on font size change for example)?

No.

Is the change of colour and getFont expensive? They don't weight much in the profiler, but maybe have heavier consequences than what it shows.

If the profiler doesn't flag it up, then it's probably nothing to worry about. That said, by careful you're not constructing new font objects every frame!

JUCEy extras

Whilst VerySleepy is a nice tool for profiling, if you've got Visual Studio to hand I'd strongly advise using its built in profiling tools. You should also check what inside of the paint function is costing you so much time. Generally speaking, you want to keep your paint function as minimal as possible (no memory allocations / new objects / heavy computations).


#6

Thanks for your answer.

 

As I couldn't find how to gain speed, I used another tactic:

Each line is a Component into which the "drawText" method was called in the paint() method. To be sure I wasn't doing anything wrong, I removed all the code from the paint() method, and instead added labels with static texts inside, without changing any color, all this in the constructor of my Component. So everything is static, nothing is created.

The result is better (still slow in Debug, but quite satisfying in Release), but not perfect. Profiling now shows that most of the time is not spent in my paint() method anymore (but in low-level methods of Juce about threading).

 

So my questions are:

  • Now that I don't do anything in my paint(), what can I do to optimize the display of texts even more (if that's possible?)?
  • Am I making the right choice using labels instead of using "drawText", especially if the text won't "move" (however, their content WILL change)?
  • I'm still interested in knowing how I could proritized the drawing of my Vu-meters over my Tracks :).

Thanks a lot for your support.


#7

I could spend forever trying to guess what's slowing your code down, but it really all comes down to profiling. Sorry!

Make sure you look at what the function itself is spending its time doing, rather than looking at the function and just seeing it takes a lot of time :)