I am trying to do background processing of assets while my app runs in the forground but I keep having problems with poor performace on the main thread and priority inversion issues. I am using a background QOS_UTILITY dispatch_async call. It seems that even though I am doing that, eventaully it calls back into the main thread during the call to requestImageDataForAsset.
It looks like something to do with core data in the underlying PhotoKit library. See the main thread below, all the work should be done in the background. Every place where there is a call to "Photos." I have put in a dispatch_async on the utility thread. Notice how the thread bounces from the QOS.UTILITY, to QOS.DEFAULT then to the main queue.
In the callback from requestImageDataForAsset After making the below listing, I put it back on the desired queue in the callback (line #19), but UI performance is still not good because the main thread is doing too much work or waiting. Is this my best option or is there something i can do to get photokit to process on my background thread?
Thread 1 Queue : com.apple.NSURLSession-work (serial)
#0 0x0000000198b1ceb8 in semaphore_wait_trap ()
#1 0x0000000100a53214 in _dispatch_semaphore_wait_slow ()
#2 0x00000001876940b0 in -[__NSURLBackgroundSession _onqueue_uploadTaskForRequest:uploadFile:bodyData:completion:] ()
#3 0x0000000187693cd8 in __80-[__NSURLBackgroundSession uploadTaskForRequest:uploadFile:bodyData:completion:]_block_invoke ()
#4 0x00000001876932fc in __68-[__NSURLBackgroundSession performBlockOnQueueAndRethrowExceptions:]_block_invoke ()
#5 0x0000000100a44df0 in _dispatch_client_callout ()
#6 0x0000000100a4e5f4 in _dispatch_barrier_sync_f_slow ()
#7 0x0000000187693280 in -[__NSURLBackgroundSession performBlockOnQueueAndRethrowExceptions:] ()
#8 0x0000000187693c68 in -[__NSURLBackgroundSession uploadTaskForRequest:uploadFile:bodyData:completion:] ()
#9 0x00000001000f5c1c in Photos.UploadDevice.(sendUploadWithUrl in _2685BBCA4A43EF0FB41323498998E5EB) (Photos.UploadDevice)(ObjectiveC.NSURL, localFileUrl : ObjectiveC.NSURL) -> Swift.Bool at /Users/possen/projects/wdp/App/Classes/UploadManager.swift:346
#10 0x00000001000f4c08 in Photos.UploadDevice.(upload in _2685BBCA4A43EF0FB41323498998E5EB) (Photos.UploadDevice)(Swift.String, fileName : Swift.String, baseUrl : Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSURL>) -> Swift.Bool at /Users/possen/projects/wdp/App/Classes/UploadManager.swift:330
#11 0x00000001000fa1e0 in Photos.UploadDevice.(uploadFile in _2685BBCA4A43EF0FB41323498998E5EB) (Photos.UploadDevice)(Swift.String, size : Swift.Int64) -> () at /Users/possen/projects/wdp/App/Classes/UploadManager.swift:537
#12 0x00000001001136ec in Photos.UploadManager.((exportAsset in _2685BBCA4A43EF0FB41323498998E5EB) (Photos.UploadManager) -> (ObjectiveC.PHAsset, name : Swift.String, device : Photos.UploadDevice) -> ()).(closure #1).(closure #2) at /Users/possen/projects/wdp/App/Classes/UploadManager.swift:770
#13 0x0000000100108b24 in partial apply forwarder for Photos.UploadManager.((exportAsset in _2685BBCA4A43EF0FB41323498998E5EB) (Photos.UploadManager) -> (ObjectiveC.PHAsset, name : Swift.String, device : Photos.UploadDevice) -> ()).(closure #1).(closure #2) ()
#14 0x0000000100113b54 in reabstraction thunk helper from @callee_owned (@owned Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSData>, @owned Swift.ImplicitlyUnwrappedOptional<Swift.String>, @unowned C.UIImageOrientation, @owned Swift.ImplicitlyUnwrappedOptional<Swift.Dictionary<ObjectiveC.NSObject, Swift.AnyObject>>) -> (@unowned ()) to @callee_owned (@in (Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSData>, Swift.ImplicitlyUnwrappedOptional<Swift.String>, C.UIImageOrientation, Swift.ImplicitlyUnwrappedOptional<Swift.Dictionary<ObjectiveC.NSObject, Swift.AnyObject>>)) -> (@out ()) at /Users/possen/projects/wdp/App/Classes/UploadManager.swift:757
#15 0x0000000100108ba8 in partial apply forwarder for reabstraction thunk helper from @callee_owned (@owned Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSData>, @owned Swift.ImplicitlyUnwrappedOptional<Swift.String>, @unowned C.UIImageOrientation, @owned Swift.ImplicitlyUnwrappedOptional<Swift.Dictionary<ObjectiveC.NSObject, Swift.AnyObject>>) -> (@unowned ()) to @callee_owned (@in (Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSData>, Swift.ImplicitlyUnwrappedOptional<Swift.String>, C.UIImageOrientation, Swift.ImplicitlyUnwrappedOptional<Swift.Dictionary<ObjectiveC.NSObject, Swift.AnyObject>>)) -> (@out ()) ()
#16 0x0000000100113ba4 in reabstraction thunk helper from @callee_owned (@in (Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSData>, Swift.ImplicitlyUnwrappedOptional<Swift.String>, C.UIImageOrientation, Swift.ImplicitlyUnwrappedOptional<Swift.Dictionary<ObjectiveC.NSObject, Swift.AnyObject>>)) -> (@out ()) to @callee_owned (@owned Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSData>, @owned Swift.ImplicitlyUnwrappedOptional<Swift.String>, @unowned C.UIImageOrientation, @owned Swift.ImplicitlyUnwrappedOptional<Swift.Dictionary<ObjectiveC.NSObject, Swift.AnyObject>>) -> (@unowned ()) at /Users/possen/projects/wdp/App/Classes/UploadManager.swift:757
#17 0x0000000100108c60 in partial apply forwarder for reabstraction thunk helper from @callee_owned (@in (Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSData>, Swift.ImplicitlyUnwrappedOptional<Swift.String>, C.UIImageOrientation, Swift.ImplicitlyUnwrappedOptional<Swift.Dictionary<ObjectiveC.NSObject, Swift.AnyObject>>)) -> (@out ()) to @callee_owned (@owned Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSData>, @owned Swift.ImplicitlyUnwrappedOptional<Swift.String>, @unowned C.UIImageOrientation, @owned Swift.ImplicitlyUnwrappedOptional<Swift.Dictionary<ObjectiveC.NSObject, Swift.AnyObject>>) -> (@unowned ()) ()
#18 0x0000000100113f3c in reabstraction thunk helper from @callee_owned (@owned Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSData>, @owned Swift.ImplicitlyUnwrappedOptional<Swift.String>, @unowned C.UIImageOrientation, @owned Swift.ImplicitlyUnwrappedOptional<Swift.Dictionary<ObjectiveC.NSObject, Swift.AnyObject>>) -> (@unowned ()) to @callee_unowned @objc_block (@unowned Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSData>, @unowned Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSString>, @unowned C.UIImageOrientation, @unowned Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSDictionary>) -> (@unowned ()) at /Users/possen/projects/wdp/App/Classes/UploadManager.swift:757
#19 0x000000018bad7380 in __65-[PHImageManager requestImageDataForAsset:options:resultHandler:]_block_invoke1437 ()
#20 0x0000000100a44e30 in _dispatch_call_block_and_release ()
#21 0x0000000100a44df0 in _dispatch_client_callout ()
#22 0x0000000100a4975c in _dispatch_main_queue_callback_4CF ()
#23 0x0000000187c5dfa4 in __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ ()
#24 0x0000000187c5c04c in __CFRunLoopRun ()
#25 0x0000000187b890a4 in CFRunLoopRunSpecific ()
#26 0x0000000190d335a4 in GSEventRunModal ()
#27 0x000000018c4be3c0 in UIApplicationMain ()
#28 0x0000000100118e58 in main at /Users/possen/projects/wdp/App/main.m:14
#29 0x0000000198a1ea08 in start ()
Enqueued from com.apple.root.default-qos (Thread 19)Queue : com.apple.root.default-qos (concurrent)
#0 0x0000000100a4dc38 in _dispatch_barrier_async_f ()
#1 0x000000018bac8df0 in __163-[PHCoreImageManager _fetchAnySizeImageAsNon5551BytesWithRequest:library:format:bestFormat:optimalSourcePixelSize:sync:fireAndForgetCPLDownload:completionHandler:]_block_invoke729 ()
#2 0x0000000100a44e30 in _dispatch_call_block_and_release ()
#3 0x0000000100a44df0 in _dispatch_client_callout ()
#4 0x0000000100a519a0 in _dispatch_root_queue_drain ()
#5 0x0000000100a52f18 in _dispatch_worker_thread3 ()
#6 0x0000000198bd12e4 in _pthread_wqthread ()
#7 0x0000000198bd0fa8 in start_wqthread ()
Enqueued from NSManagedObjectContext 0x15fd29310 (Thread 19)Queue : NSManagedObjectContext 0x15fd29310 (serial)
#0 0x0000000100a4655c in dispatch_async ()
#1 0x000000018baca94c in __163-[PHCoreImageManager _fetchAnySizeImageAsNon5551BytesWithRequest:library:format:bestFormat:optimalSourcePixelSize:sync:fireAndForgetCPLDownload:completionHandler:]_block_invoke_2808 ()
#2 0x000000018bacad60 in __163-[PHCoreImageManager _fetchAnySizeImageAsNon5551BytesWithRequest:library:format:bestFormat:optimalSourcePixelSize:sync:fireAndForgetCPLDownload:completionHandler:]_block_invoke_2813 ()
#3 0x000000018bac499c in __226-[PHCoreImageManager _fetchAnySizeImageAsNon5551BytesPossiblyThruAssetsdAndCPLWithRequest:library:format:optimalSourcePixelSize:wantsProperties:networkAccessAllowed:networkAccessForced:trackCPLDownload:sync:completionHandler:]_block_invoke ()
#4 0x000000018bac45d0 in -[PHCoreImageManager _fetchAnySizeImageAsNon5551BytesPossiblyThruAssetsdAndCPLWithRequest:library:format:optimalSourcePixelSize:wantsProperties:networkAccessAllowed:networkAccessForced:trackCPLDownload:sync:completionHandler:] ()
#5 0x000000018bacaa8c in __163-[PHCoreImageManager _fetchAnySizeImageAsNon5551BytesWithRequest:library:format:bestFormat:optimalSourcePixelSize:sync:fireAndForgetCPLDownload:completionHandler:]_block_invoke812 ()
#6 0x000000019291b2b0 in __82-[PLPhotoLibrary _withDispatchGroup:synchronously:performBlock:completionHandler:]_block_invoke ()
#7 0x00000001879f9270 in developerSubmittedBlockToNSManagedObjectContextPerform ()
#8 0x0000000100a44df0 in _dispatch_client_callout ()
#9 0x0000000100a4f854 in _dispatch_queue_drain ()
#10 0x0000000100a48120 in _dispatch_queue_invoke ()
#11 0x0000000100a5175c in _dispatch_root_queue_drain ()
#12 0x0000000100a52f18 in _dispatch_worker_thread3 ()
#13 0x0000000198bd12e4 in _pthread_wqthread ()
#14 0x0000000198bd0fa8 in start_wqthread ()
Enqueued from com.apple.root.default-qos (Thread 25)Queue : com.apple.root.default-qos (concurrent)
#0 0x0000000100a4dc38 in _dispatch_barrier_async_f ()
#1 0x000000019291b278 in -[PLPhotoLibrary _withDispatchGroup:synchronously:performBlock:completionHandler:] ()
#2 0x000000018baca8cc in __163-[PHCoreImageManager _fetchAnySizeImageAsNon5551BytesWithRequest:library:format:bestFormat:optimalSourcePixelSize:sync:fireAndForgetCPLDownload:completionHandler:]_block_invoke807 ()
#3 0x0000000100a4da28 in _dispatch_block_async_invoke_and_release ()
#4 0x0000000100a44df0 in _dispatch_client_callout ()
#5 0x0000000100a519a0 in _dispatch_root_queue_drain ()
#6 0x0000000100a52f18 in _dispatch_worker_thread3 ()
#7 0x0000000198bd12e4 in _pthread_wqthread ()
#8 0x0000000198bd0fa8 in start_wqthread ()
Enqueued from com.apple.root.utility-qos (Thread 24)Queue : com.apple.root.utility-qos (concurrent)
#0 0x0000000100a52b7c in _dispatch_async_f_slow ()
#1 0x000000018bac6e7c in -[PHCoreImageManager _fetchAnySizeImageAsNon5551BytesWithRequest:library:format:bestFormat:optimalSourcePixelSize:sync:fireAndForgetCPLDownload:completionHandler:] ()
#2 0x000000018bacf618 in -[PHCoreImageManager _processImageRequest:sync:] ()
#3 0x000000018bad3214 in -[PHImageManager requestAsynchronousImageForAsset:chainedToMasterRequest:targetSize:contentMode:options:resultHandler:] ()
#4 0x000000018bad3048 in -[PHImageManager requestAsynchronousImageForAsset:targetSize:contentMode:options:resultHandler:] ()
#5 0x000000018bad6ec4 in -[PHImageManager requestImageDataForAsset:options:resultHandler:] ()
#6 0x0000000100111cc4 in Photos.UploadManager.((exportAsset in _2685BBCA4A43EF0FB41323498998E5EB) (Photos.UploadManager) -> (ObjectiveC.PHAsset, name : Swift.String, device : Photos.UploadDevice) -> ()).(closure #1) at /Users/possen/projects/wdp/App/Classes/UploadManager.swift:755
#7 0x000000010009d958 in reabstraction thunk helper from @callee_owned () -> (@unowned ()) to @callee_unowned @objc_block () -> (@unowned ()) at /Users/possen/projects/wdp/App/Classes/CameraRollController.swift:50
#8 0x0000000100a44e30 in _dispatch_call_block_and_release ()
#9 0x0000000100a44df0 in _dispatch_client_callout ()
#10 0x0000000100a519a0 in _dispatch_root_queue_drain ()
#11 0x0000000100a52f18 in _dispatch_worker_thread3 ()
#12 0x0000000198bd12e4 in _pthread_wqthread ()
#13 0x0000000198bd0fa8 in start_wqthread ()
Enqueued from NSOperationQueue 0x170434820 :: NSOperation 0x1742564d0 (Thread 17)Queue : NSOperationQueue 0x170434820 :: NSOperation 0x1742564d0 (serial)
#0 0x0000000100a52b7c in _dispatch_async_f_slow ()
#1 0x0000000100102ddc in Photos.UploadManager.(exportAsset in _2685BBCA4A43EF0FB41323498998E5EB) (Photos.UploadManager)(ObjectiveC.PHAsset, name : Swift.String, device : Photos.UploadDevice) -> () at /Users/possen/projects/wdp/App/Classes/UploadManager.swift:739
#2 0x000000010010fc2c in Photos.UploadDevice.((processAssets in _2685BBCA4A43EF0FB41323498998E5EB) (Photos.UploadDevice) -> () -> ()).(closure #1).(closure #1) at /Users/possen/projects/wdp/App/Classes/UploadManager.swift:507
#3 0x000000010010ca70 in Photos.UploadDevice.(fetchRemoteDirList (Photos.UploadDevice) -> (ObjectiveC.NSURL, block : (Swift.Optional<Swift.Dictionary<Swift.String, Photos.FileEntry>>, Swift.Optional<ObjectiveC.NSError>) -> ()) -> ()).(closure #2) at /Users/possen/projects/wdp/App/Classes/UploadManager.swift:284
#4 0x000000010010b198 in reabstraction thunk helper from @callee_owned (@owned Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSData>, @owned Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSURLResponse>, @owned Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSError>) -> (@unowned ()) to @callee_owned (@in (Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSData>, Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSURLResponse>, Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSError>)) -> (@out ()) at /Users/possen/projects/wdp/App/Classes/UploadManager.swift:236
#5 0x00000001000f3aec in partial apply forwarder for reabstraction thunk helper from @callee_owned (@owned Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSData>, @owned Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSURLResponse>, @owned Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSError>) -> (@unowned ()) to @callee_owned (@in (Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSData>, Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSURLResponse>, Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSError>)) -> (@out ()) with unmangled suffix "52" ()
#6 0x000000010010b3ec in reabstraction thunk helper from @callee_owned (@in (Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSData>, Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSURLResponse>, Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSError>)) -> (@out ()) to @callee_owned (@owned Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSData>, @owned Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSURLResponse>, @owned Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSError>) -> (@unowned ()) at /Users/possen/projects/wdp/App/Classes/UploadManager.swift:236
#7 0x000000010010b444 in reabstraction thunk helper from @callee_owned (@owned Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSData>, @owned Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSURLResponse>, @owned Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSError>) -> (@unowned ()) to @callee_unowned @objc_block (@unowned Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSData>, @unowned Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSURLResponse>, @unowned Swift.ImplicitlyUnwrappedOptional<ObjectiveC.NSError>) -> (@unowned ()) at /Users/possen/projects/wdp/App/Classes/UploadManager.swift:236
#8 0x000000018763b2d4 in __49-[__NSCFLocalSessionTask _task_onqueue_didFinish]_block_invoke ()
#9 0x0000000188b5f508 in __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ ()
#10 0x0000000188ab0c94 in -[NSBlockOperation main] ()
#11 0x0000000188aa061c in -[__NSOperationInternal _start:] ()
#12 0x0000000188b6226c in __NSOQSchedule_f ()
#13 0x0000000100a44df0 in _dispatch_client_callout ()
#14 0x0000000100a4f854 in _dispatch_queue_drain ()
#15 0x0000000100a48120 in _dispatch_queue_invoke ()
#16 0x0000000100a5175c in _dispatch_root_queue_drain ()
#17 0x0000000100a52f18 in _dispatch_worker_thread3 ()
#18 0x0000000198bd12e4 in _pthread_wqthread ()
#19 0x0000000198bd0fa8 in start_wqthread ()