So I ran a similar experiment to your timerCallback one with a 10ms interval, here were my findings
With your test project (CodeEditorTest3), I see a similar pattern of results. However, my results aren’t as extreme, instead of ~75ms I was getting ~25ms
If I stop adding messages to the CodeEditor and instead log them using DBG I don’t see the same issue
Disabling font fallback on the font in the CodeEditor significantly improves the situation for me, although it doesn’t eradicate the issue (the peak callback time dropped to ~15ms)
Increasing the timer interval to roughly the peak time (in my case~25ms) effectively avoids the pattern
An interesting observation I had was that the issue doesn’t occur until the text exceeds the end of the visible page, causing scrolling
In addition to that observation I found if the window is made small enough with fewer lines of text I no longer observe the same behaviour (at least at a 10ms interval), and a larger window gets worse
In a profiler the hot path is preoccupied by shaping and other text/font rendering
In summary I’m still not convinced there is a problem with AsyncUpdater or Timer. The observed behaviour appears to be caused by the newer text rendering. As I said before we are aware of this and some work will be carried out but the performance is not likely to ever be exactly the same as it was before.
For those following this thread with much interest, albeit possibly quite glib, could you guys please update us with the OS you are testing on - is it Windows or MacOS? What style of scrollbar do you have enabled on your EditorComponents?
My experience with other frameworks has led me to always be quite suspicious of issues surrounding scrolling performance, in general, as different OS’s have different problems with this, imho …
Very simple, you just need to call setFallbackEnabled (false) on the font in question. For example…
auto f = messageDisplay->getFont();
f.setFallbackEnabled (false);
messageDisplay->setFont (f);
I found it slightly more erratic to measure but fundamentally I suspect it is just subject to the same issue but I think because it doesn’t have a set time in which it should be arriving the overall measurements are just more erratic. It’s easier to spot the pattern with Timer.
MacOS 11.10.7. Intel. All of the discussions in here reference a test app with whatever the default scrollbar is; also in my real app I’m doing nothing special about a scrollbar; it’s the default.
I can confirm that disabling font fallback improves text rendering performance quite a bit. Still not at juce 7 levels though, and disabling fallback is not an option if you have any customers who want to use their own languages as text input. Which we do.
As I’ve said above text rendering will inherently be more expensive than it was before because there is more it can do. How did you get on with using the AffineTransform? anything you can do on your end to prevent the need to reshape the text should have a very positive impact on performance. We already perform caching for this reason but if significant amounts of text are constantly being reshaped the cache isn’t going to help.
Does this include scale modification? This is a pretty common way of handling window resizing. Does having a component at non unity scale severely impact text rendering performance?
OK, here’s an example project showing very poor performance of a simple tableview with scroller. Scroll up and down with click-drag or with mouse wheel.
I switch global paths between juce6 and juce8 and the difference is masssssssive.
There are 2 versions of TableListBoxModel subclasses in here you can try - one which uses drawText for every cell paint, and another which creates juce::Labels for every cell and then never touches them again. In both cases, the Juce8 performance is very poor compared to juce6. Haven’t tried juce7 as I don’t have a copy lying around but in earlier tests 7 was comparable to 6.
@thecargocult thanks for sharing. I think the problem here is just that the cache gets overwhelmed with all the different glyph arrangements so everything keeps getting reshaped as a result. Could you please try applying the following change and letting me know how that works for you?
As always it’s a little complicated, in a lot of cases increasing the cache size may well improve things but each case warrants a closer investigation as other methods may be even better. The problem with growing the cache is you’re just pushing the problem out. That being said I think it should be bigger than it currently is. There may be other more intelligent ways we could cache (or choose not to!) in some circumstances too.
I’m fairly sure this will ultimately boil down to an AffineTransform, I wouldn’t expect the font size to change as a result of window resizing. Unless you are tracking your own scale factor and multiplying by some font size? If it does come down to an AffineTransform there should be no additional reshaping. If you have a specific use case in mind you’re concerned about please share an example and I’ll try to confirm either way for you.
I’v not tested (I’ll confirm tomorrow), but just by looking at it I wouldn’t expect so as the font size remains the same and the Component has an AffineTransform applied via setTransform. So reshaping is already being avoided.
If there were a problem then in most cases it would only have an impact while resizing. It’s only in more extreme cases (such as lots of different text spread across lots of components) that the cache could become so overwhelmed that it’s effectively made redundant.
from what I’ve seen I would expect it to make a difference. Anywhere in our app that we had lots of text being scrolled around, this cache size change has improved performance.