3

For performance debugging purposes, I need to watch the progress of my UI updates whenever a background task, operated by a GCD concurrency queue, finishes one of its tasks.

Without an artificial delay it is very hard to follow and react to what's happening.

Every single task takes maybe 10ms. I like it to take one second instead.

I tried slowing down the queue's task by adding a sleep(1); to it, but that will allow other waiting tasks to run.

What I need is that each task really keeps occupying its queue until that extra second is over.

How do I do that without having to reorganize my entire queuing code? After all, this is only for debugging, and I'd like to just insert that code with conditional compilation instead of ending up with different code for debug and non-debug builds.

Thomas Tempelmann
  • 11,045
  • 8
  • 74
  • 149
  • 1
    By the way, in addition to spinning like I described before, I find using “Points of Interest” in Instruments very useful for getting visual representations (and correlating other things in instruments, such as time profiler, allocations, etc.). See https://stackoverflow.com/q/19017843/1271826 – Rob Mar 30 '19 at 20:52

2 Answers2

1

You can spin for a certain period of time, e.g.:

func spin(for interval: CFTimeInterval) {
    let start = CACurrentMediaTime()
    while (CACurrentMediaTime() - start) < interval { }
}

So, to keep a thread busy for 1 second, it would be:

spin(for: 1)

You’d never do this in a production app, but it might serve your diagnostic purposes.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
1

I also came up with a way in the meantime, effectively the same as Rob's, by killing time in a loop:

mach_timebase_info_data_t tb;
mach_timebase_info (&tb);
double tbScale = 1.0 / (1e-9 * (double)tb.numer / (double)tb.denom);
uint64_t now, end = mach_absolute_time();
end += tbScale * 0.5; // -> wait 0.5 sconds
do {
    now = mach_absolute_time();
} while (now < end);
Thomas Tempelmann
  • 11,045
  • 8
  • 74
  • 149
  • Yep, that works. The [`CACurrentMediaTime`](https://developer.apple.com/documentation/quartzcore/1395996-cacurrentmediatime?language=occ) is “A `CFTimeInterval` derived by calling `mach_absolute_time()` and converting the result to seconds.” So, it’s basically the same idea. ;) – Rob Mar 30 '19 at 20:57