• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
More thread scheduling observations
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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.

  • Follow-Ups:
    • Re: More thread scheduling observations
      • From: Bill Stewart <email@hidden>
    • Re: More thread scheduling observations
      • From: James McCartney <email@hidden>
  • Prev by Date: Re: Soundfont sf2 support
  • Next by Date: Re: More thread scheduling observations
  • Previous by thread: Re: Soundfont sf2 support
  • Next by thread: Re: More thread scheduling observations
  • Index(es):
    • Date
    • Thread