ios - How to parallelize many (100+) tasks without hitting global GCD limit? -


the problem:

when lazy-loading list of 100+ icons in background, hit gcd thread limit (64 threads), causes app freeze semaphore_wait_trap on main thread. want restructure threading code prevent happening, while still loading icons asynchronous prevent ui blocking.

context:

my app loads screen svg icons on it. amount differs on average 10-200. icons drawn using local svg image or remote svg image (if has custom icon), post-processed final image result.

because takes time, , aren't vital user, want load , post-process them in background, pop in on time. every icon use following:

dispatch_queue_t concurrentqueue = dispatch_get_global_queue(dispatch_queue_priority_default, 0); dispatch_async(concurrentqueue, ^{     //code executed in background     svgkimage *iconimage = [settings geticonimage:location];     dispatch_async(dispatch_get_main_queue(), ^{         //code executed on main thread when background task finished         if (iconimage) {             [iconimgview setimage:iconimage.uiimage];         }     }); }); 

the geticonimage method handles initial loading of base svg, reads synchronized [nsinputstream inputstreamwithfileatpath:path] if local, , [nsurlconnection sendsynchronousrequest:request returningresponse:&response error:&errorwithnsdata] if should load remotely. happens synchronous.

then there post-processing of recoloring svg, before gets returned , put in uiimageview on main thread.

question:

is there way structure code allow parallelized background loading prevent deadlock because of many threads?

solution edit:

_iconoperationqueue = [[nsoperationqueue alloc]init]; _iconoperationqueue.maxconcurrentoperationcount = 8;      // code executed on background [_iconoperationqueue addoperationwithblock:^{     // i/o code     svgkimage *baseicon = [settings geticonbasesvg:location];      // cpu-only code     svgkimage *iconimage = [settings geticonimage:location withbasesvg:baseicon];     uiimage *svgimage = iconimage.uiimage; // converting svgkimage uiimage expensive, don't on main thread     [[nsoperationqueue mainqueue] addoperationwithblock:^{         // code executed on main thread when background task finished         if (svgimage) {             [iconimgview setimage:svgimage];         }     }]; }]; 

instead of directly using gcd concurrent queue, use nsoperationqueue. set maxconcurrentoperationcount reasonable, 4 or 8.

if can, should separate i/o pure computation. use width-restricted operation queue i/o. pure computation can use unrestricted operation queue or pure gcd for.

the reason i/o blocks. gcd detects system idle , spins worker thread , starts task queue. blocks in i/o, too, more until hits limit. then, i/o starts completing , tasks unblock. have oversubscribed system resources (i.e. cpu) because there more tasks in flight cores , using cpu instead of being blocked i/o.

pure computation tasks don't provoke problem because gcd sees system busy , doesn't dequeue more tasks until earlier ones have completed.


Comments

Popular posts from this blog

powershell Start-Process exit code -1073741502 when used with Credential from a windows service environment -

twig - Using Twigbridge in a Laravel 5.1 Package -

c# - LINQ join Entities from HashSet's, Join vs Dictionary vs HashSet performance -