So I restructured a central part in my Cocoa application (I really had to!) and I am running into issues since then.

Quick outline: my application controls the playback of QuickTime movies so that they are in sync with external timecode.

Thus, external timecode arrives on a CoreMIDI callback thread and gets posted to the application about 25 times per sec. The sync is then checked and adjusted if it needs to be. All this checking and adjusting is done on the main thread.

Even if I put all the processing on a background thread it would be a ton of work as I'm currently using a lot of GCD blocks and I would need to rewrite a lot of functions so that they can be called from NSThread. So I would like to make sure first if it will solve my problem.

The problem

My Core MIDI callback is always called in time, but the GCD block that is dispatched to the main queue is sometimes blocked for up to 500 ms. Understandable that adjusting the sync does not quite work if that happens. I couldn't find a reason for it, so I'm guessing that I'm doing something that blocks the main thread.

I'm familiar with Instruments, but I couldn't find the right mode to see what keeps my messages from being processed in time.

I would appreciate if anyone could help. Don't know what I can do about it. Thanks in advance!

有帮助吗?

解决方案 2

You may be blocking the main thread or you might be flooding it with events.

I would suggest three things:

  • Grab a timestamp for when the timecode arrives in the CoreMIDI callback thread (see mach_absolute_time(). Then grab the current time when your main thread work is being done. You can then adjust accordingly based on how much time has elapsed between posting to the main thread and it actually being processed.

  • create some kind of coalescing mechanism such that when your main thread is blocked, interim timecode events (that are now out of date) are tossed. This can be as simple as a global NSUInteger that is incremented every time an event is received. The block dispatched to the main queue could capture the current value on creation, then check it when it is processed. If it differs by more than N (N for you to determine), then toss the event because more are in flight.

  • consider not sending an event to the main thread for every timecode notification. 25 adjustments per second is a lot of work. If processing only 5 per second yields a "good enough" perceptual experience, then that is an awful lot of work saved.

In general, instrumenting the main event loop is a bit tricky. The CPU profiler in Instruments can be quite helpful. It may come as a surprise, but so can the Allocations instrument. In particular, you can use the Allocations instrument to measure memory throughput. If there are tons of transient (short lived) allocations, it'll chew up a ton of CPU time doing all those allocations/deallocations.

其他提示

Watchdog

You can use watch dog that stop when the main thread stopped for time

https://github.com/wojteklu/Watchdog

you can install it using cocoapod

pod 'Watchdog'
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top