From db085c49bea0b32d33308dabda7bf4396e6a6431 Mon Sep 17 00:00:00 2001 From: Nadine Salter Date: Tue, 2 Dec 2014 18:31:54 -0800 Subject: [PATCH] Support realistic display delays (for debugging). ASDISPLAYNODE_DELAY_DISPLAY unconditionally delays *all* attempts to execute display blocks, even those that have been cancelled. Fix that. The DELAY_DISPLAY debugging tool is intended to simulate the effect of expensive draw calls -- it lets you test your app's behaviour under conditions potentially even worse than an iPhone 4. Unfortunately, the current simulation is unusably incorrect, as can be demonstrated by repeatedly scrolling up and down in the Kittens example project. ASRangeController enqueues asynchronous display of ASTableView cell nodes when they enter the working range, and suspends their display when they exit. On a slow device, this performs as desired, limiting expensive display computation to the space of the working range. In the DELAY_DISPLAY simulation, the suspended displays are as expensive as the executed ones, so ASRangeController becomes unusably slow. --- .../Private/ASDisplayNode+AsyncDisplay.mm | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/AsyncDisplayKit/Private/ASDisplayNode+AsyncDisplay.mm b/AsyncDisplayKit/Private/ASDisplayNode+AsyncDisplay.mm index ee885a9e14..3e906a8225 100644 --- a/AsyncDisplayKit/Private/ASDisplayNode+AsyncDisplay.mm +++ b/AsyncDisplayKit/Private/ASDisplayNode+AsyncDisplay.mm @@ -22,11 +22,14 @@ #if ASDISPLAYNODE_DELAY_DISPLAY static long __ASDisplayLayerMaxConcurrentDisplayCount = 1; +#define ASDN_DELAY_FOR_DISPLAY() usleep( (long)(0.1 * USEC_PER_SEC) ) #else // Basing this off of CPU core count would make sense, but first some experimentation should be done to understand // if having more ready-to-run work keeps the CPU clock up (or other interesting scheduler effects). static long __ASDisplayLayerMaxConcurrentDisplayCount = 8; +#define ASDN_DELAY_FOR_DISPLAY() #endif + static dispatch_semaphore_t __ASDisplayLayerConcurrentDisplaySemaphore; /* @@ -48,11 +51,6 @@ static void __ASDisplayLayerIncrementConcurrentDisplayCount(BOOL displayIsAsync, dispatch_semaphore_wait(__ASDisplayLayerConcurrentDisplaySemaphore, DISPATCH_TIME_FOREVER); } - -#if ASDISPLAYNODE_DELAY_DISPLAY - usleep( (long)(0.05 * USEC_PER_SEC) ); -#endif - } /* @@ -173,12 +171,13 @@ static void __ASDisplayLayerDecrementConcurrentDisplayCount(BOOL displayIsAsync, displayBlock = ^id{ __ASDisplayLayerIncrementConcurrentDisplayCount(asynchronous, rasterizing); - if (isCancelledBlock()) { __ASDisplayLayerDecrementConcurrentDisplayCount(asynchronous, rasterizing); return nil; } + ASDN_DELAY_FOR_DISPLAY(); + UIGraphicsBeginImageContextWithOptions(bounds.size, opaque, contentsScaleForDisplay); for (dispatch_block_t block in displayBlocks) { @@ -208,6 +207,8 @@ static void __ASDisplayLayerDecrementConcurrentDisplayCount(BOOL displayIsAsync, return nil; } + ASDN_DELAY_FOR_DISPLAY(); + UIImage *result = [nodeClass displayWithParameters:drawParameters isCancelled:isCancelledBlock]; __ASDisplayLayerDecrementConcurrentDisplayCount(asynchronous, rasterizing); return result; @@ -227,13 +228,13 @@ static void __ASDisplayLayerDecrementConcurrentDisplayCount(BOOL displayIsAsync, displayBlock = ^id{ __ASDisplayLayerIncrementConcurrentDisplayCount(asynchronous, rasterizing); - - // Short-circuit to be efficient in the case where we've already started a different -display. if (isCancelledBlock()) { __ASDisplayLayerDecrementConcurrentDisplayCount(asynchronous, rasterizing); return nil; } + ASDN_DELAY_FOR_DISPLAY(); + if (!rasterizing) { UIGraphicsBeginImageContextWithOptions(bounds.size, opaque, contentsScaleForDisplay); }