DocumentWindow resize performance


#1

I want to raise a question that has bugged me for a while, though must admit it’s a kind of superficial.

On OSX - live-resizing an empty JUCE DocumentWindow (native or not) is slightly choppy, compared to the smoothness of, say, the main window of an empty Cocoa project, a Finder window, or other native apps like Skim or Sublime Text. By slightly choppy, I mean that the window frame appears to be redrawn roughly half as many times for a JUCE main window relative to apps that resize more smoothly. I see this behavior on 10.11 and 10.12, with or without release-build optimizations enabled, and with or without OpenGL rendering attached to the main window. Disabling CoreGraphics seems to make it worse.

Where might the overhead come from? It seems to me that ComponentPeer is a very thin wrapper around NSWindow and not likely to be the source of overhead. Has anybody looked into this?


#2

That’s not what I see on my mac… Even quite complex windows like Projucer are just as smooth as things like finder.


#3

Ok, interesting. To be clear, I also get excellent performance in resizing complex layouts, within a main window, e.g. with ResizableBorderComponent. The effect I’m seeing occurs in top-level windows (even empty ones), and it really is quite subtle. It also becomes more noticeable for larger windows, filling most of the screen. BTW, I see the same behavior in GLFW top-level windows, but raw NSWindow is perfectly smooth. Maybe my machine is just old…


#4

Yeah, I’ve sometimes seen OSX throttling the update rate for apps under some circumstances. Not sure why or when it decides to do that, but most likely this isn’t an actual problem, just a weird OS behaviour.


#5

Hey Jules, I stumbled on the solution to this! Just give the NSWindow instance a backing layer:

window.contentView.wantsLayer = YES;

As it turns out this is the default when you create an empty Xcode app, but it’s not when programmatically creating a new NSWindow instance. Wow.


#6

Well, that could be easily added in juce_mac_NSViewComponentPeer.mm, line 114:

    [view setWantsLayer: YES];

…but I just had a quick try and it didn’t seem to make the slightest bit of difference. What exactly are you saying this does?


#7

I’ve made this same change, and I definitely notice an improved frame rate during live resizes. I profiled it to be sure it’s not my imagination. While dragging a window corner, the time between resize events hitting the main content component is typically 30 - 60 ms without the backing layer, and 10 - 20 ms with it.


#8

OK… I’m being a bit hesitant here because I suspect that there’ll be some differences here depending on the type of machine, version of the OS, content being drawn, and probably other things like number of windows, GPU memory pressure etc., and regardless of what’s happening in your case, I wouldn’t be surprised if this has negative effects in other contexts.

Not really sure what the right call is here, TBH, we don’t have enough data!


#9

Would you consider adding something like ComponentPeer::StyleFlags::windowWantsBackingLayer?


#10

No, definitely not, those flags are intended to be cross-platform.

It could be that actually, enabling the flag globally is fine, we’d just need to know a bit more about its pros and cons before deciding.