More thread scheduling observations
More thread scheduling observations
- Subject: More thread scheduling observations
- From: Kurt Revis <email@hidden>
- Date: Sat, 4 May 2002 03:49:06 -0700
I spent some time yesterday playing around with my code which implements
a feeder thread (reading audio from a file) which communicates with my
IOProc via a ring buffer. I have some interesting observations --
anyone have any experience with this sort of thing, or comments?
* The easiest way to cause dropouts is to drag a fairly large window,
continuously, for a large period of time. Even if nothing else is
happening on the machine, it seems that the window server process gets
priority and starves out my feeder thread.
A good way to see this is with the 'latency' tool (/usr/bin/latency). I
just ran it and dragged a window around, continously, for a while. Sure
enough, the maximum latency(usecs) went up to 13237437 ... that's 13
seconds!
So it appears that the worst-case wakeup time for an ordinary thread is
essentially unbounded. The best one can do in this situation is to have
a really big buffer between the feeder thread and the IOProc, and assume
that one's users won't be terribly cruel.
* Other kinds of load are not nearly so bad for scheduling. I can do an
'ls -lR /' in a terminal window and have iTunes running a big
visualizer, and the machine definitely gets less responsive, but my
feeder thread still wakes up pretty close to when I want. All this other
work is happening in processes with ordinary priority, as far as I know,
which explains why they are not causing problems. It's the high-priority
window server process that is causing the problems seen above.
* iTunes is really good. I have great difficulty getting it to drop out,
even when I torture the window server. (I have heard dropouts at other
times, like when I scroll the view in Mail that I'm typing in right now.
But I can't get it to happen intentionally.)
How does iTunes do it? I am guessing that it has a big buffer -- vmmap
shows that it has a big chunk of memory allocated (8704K), but I haven't
verified that that's actually an audio buffer. (And maybe it's just used
for those 12-second crossfades.) I haven't delved in to check its
threads' scheduling policies, either.
* The QuickTime player, on the other hand, is pretty poor. It is
surprisingly easy to cause dropouts by dragging a window around while
it's playing. I don't feel so bad about my code after noticing this :)
* I was just using read() to get my samples from an AIFF file. Then I
started using QuickTime to read the samples, using the technique in this
example:
http://developer.apple.com/samplecode/Sample_Code/Sound/MP3Player.htm
This uses GetMediaSample() in QT to read samples from a file, and then
the SoundConverter (QT/Sound Manager) to do decompression and format
conversion.
Unfortunately, doing this seems to make my program much more susceptible
to dropouts. I'm not sure why this would be happening, though. (And I'm
not sure how to measure the effect exactly.) The only thing I can think
of is that the QT calls are somehow causing my feeder thread to block
more often. Anybody have any ideas?
* While investigating the above, I noticed that the Sound Manager
installs its own IOProc, even though I'm not using it to play any sound.
(This seems to get set up when I first create a QT movie.) This is
probably not a big deal (although I wish it weren't there taking up
processor time). However, I noticed that this IOProc is calling
pthread_mutex_lock() every time through! Isn't that exactly what we've
been told not to do?
I thought perhaps my problems with QT were related to this, because
GetMediaSample() and the SoundConverter also lock some mutexes. However,
it doesn't seem that they are trying to lock the same mutex as the
IOProc, so this is probably not the problem.
* If I set my feeder thread to use the time-contraint policy, it works
fantastically well. Even with a tiny (64k) ring buffer, I can't get it
to drop out. So I'd really like to know why this approach is not
recommended. (Maybe if I were reading a file over the network, or some
other slow medium, things would not be so wonderful?)
* Instead of that policy, I tried setting my thread's precedence
(THREAD_PRECEDENCE_POLICY) to a high value. This is not as fantastically
reliable as the time-constraint policy, but it does seem to help a great
deal. Even with a small buffer (256k) it is pretty hard to get
dropouts... about as hard as when I used a 4 MB buffer with an ordinary
thread. This seems like the best tradeoff to use, so far.
Apple guys: I know Bill Stewart said that you'd be discussing this at
WWDC this year. Unfortunately we can't all be there--can I ask that you
summarize the issues somewhere public, like on this list or in a
technote or something? Thanks!
--
Kurt Revis
email@hidden
_______________________________________________
coreaudio-api mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/coreaudio-api
Do not post admin requests to the list. They will be ignored.