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.
This commit is contained in:
Nadine Salter
2014-12-02 18:31:54 -08:00
parent 4cd110e630
commit db085c49be

View File

@@ -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);
}