Why are CATiledLayers drawing on a single thread in 10.14 and 10.15?

I have a macOS application (commercial GIS Package) that's been shipping since 2009 which uses `CATiledLayer` to draw large areas for map presentation. I've had no problems with this since the early days of Core Animation. However, it appears that since 10.14 and now with 10.15, my `CATiledLayer` is drawing on a single thread.


My `-drawLayer:inContext:` delegate is being called from a background thread, not the main thread. However, it's being called sequentially with each tile that need to be drawn. The result is a very bored machine and a huge drop in performance from the same version running in 10.13 and prior. In 10.13 and prior, the `drawLayer:inContext` is being called on multiple threads with multiple contexts to draw the tiles.


The layer is in an `NSView` subclass.


The queue is named `CADispatch Group (serial)` and the stack from before the call to our delegate method is:


Thread 138 Queue : CA DispatchGroup (serial)
#0 0x00000001001c6a0e in -[MapView drawLayer:inContext:]
#1 0x00007fff3f2d19fc in -[CALayer drawInContext:] ()
#2 0x00007fff3f3b6f6a in tiled_layer_render(_CAImageProvider*, unsigned int, unsigned int, unsigned int, unsigned int, void*) ()
#3 0x00007fff3f454871 in CAImageProviderThread(unsigned int*, bool) ()
#4 0x0000000107c42826 in _dispatch_client_callout ()
#5 0x0000000107c49dd7 in _dispatch_lane_serial_drain ()
#6 0x0000000107c4ab90 in _dispatch_lane_invoke ()
#7 0x0000000107c57fe0 in _dispatch_workloop_worker_thread ()
#8 0x0000000107cd0361 in _pthread_wqthread ()
#9 0x0000000107ccf49b in start_wqthread ()

In hopes of finding something trivial like a dependence on settings in the View, I've created a completely new, unadorned window with nothing but the MapView in it.


I'm certain there's only one thread calling in as I have a protected counter (predates this problem) which grows proportionately with the are being drawn on 10.13.6, but it remains just 1 on 10.15.4 and on 10.14.6. (Also, I am printing the thread ID and it's the same thread on each consecutive call under 10.14 and 10.15).


I've tried reducing the CALayer stack for the NSView subclass so that it is just a single CALayer with my CATiledLayer inside it (previously, there were a stack of other layers here), but that had no effect.


The NSView is loaded with a NIB as part of an NSWindow (this hasn't changed in a decade), but I have tried changing from the previous CALayer instantiation (adding the CALayer and setting wantsLayer)


I have been able to reproduce this on our previous shipping version (linked against 10.7) and against a version linked against 10.13. The symptoms are the same.


I'm looking for any other suggestions at this point. Something changed in running this on 10.14 and 10.15, and I haven't been able to locate an indicator in the release notes.


Any indication of what we're doing wrong, or what's running afoul of macOS 10.14+ would be greatly appreciated.

Replies

Is your CALayer’s drawsAsynchronously property specifically set to true? I don’t know if this was already the case in 10.13 and below, but it’s now set to false by default.
This might have nothing to do with your issue but we experienced the same problem with our background reporting threads where they suddenly took forever to run. We solved that by setting the thread or queue priority to be user interactive (or something like that). Sorry I don't have the details in front of me.

I have no idea if you can do the same with the drawing threads for CATiledLayer - or whether this the issue but thought it was worth mentioning.

Let us know if you find the solution.