Threading unfairness

Matt Kimball matt at kimball.net
Sat May 18 16:54:36 EDT 2002


While writing some multithreaded GUI code with ActivePython 2.2.1 under Windows
XP, on a single processor machine, and I noticed that my user-interface thread
was very unresponsive when I had a background computation thread going.  This
annoyed me.  It seemed like the main thread where the GUI code was running was
being starved of CPU time.  Since there doesn't seem to be any way to set thread
priorities with Python, I "fixed" the problem with inserting frequent
'time.sleep(0)' calls in my compute-intensive thread, and that seemed to give my
main GUI thread more time to execute when a user-interface event occurred.  

However, it got me wondering just how bad the situation was, so I wrote a simple
program to test Python threads, and find the maximum time that individual
threads go without getting any CPU time.  Interestingly, the problem seems worse
with a low number of threads.  In the case of only the main thread and one
thread spawned by the main thread, I see execution gaps of ~0.25 seconds.  That
is, each thread is getting a full 0.25 second execution time without the other
thread executing at all!  However, if I increase the number of thread spawned by
the main thread to 10, it seems much better.  Nine out of ten spawned thread and
the main thread have a maximum gap time of ~0.005 seconds, which seems much more
reasonable to me, but the first thread spawned by the main thread has an
execution gap of ~0.17 seconds, every time.

Here is a typical case of one spawned thread:

  Thread   Gap time

  main     0.241325084613
  thread1  0.292677141927

Three spawned threads:

  Thread   Gap time

  main     0.100827339788
  thread1  0.163031893718
  thread2  0.100502438159
  thread3  0.100673130244

Five spawned threads:

  Thread   Gap time

  main     0.00585884518841
  thread1  0.174716898377
  thread2  0.00717269932352
  thread3  0.00577838803542
  thread4  0.00579235629107
  thread5  0.00580353089572


Ten spawned threads:

  Thread   Gap time

  main     0.00570351818465
  thread1  0.175031463496
  thread10 0.00545823561356
  thread2  0.00513724509665
  thread3  0.00610692141026
  thread4  0.0051269085875
  thread5  0.00494085142122
  thread6  0.0050587434996
  thread7  0.00564568960567
  thread8  0.00589795630435
  thread9  0.00749285174516


The code I used to measure this is at http://matt.kimball.net/test_thread.py -- 
Maybe someone wants to look it over to make sure I'm not doing anything funny,
and run a few tests on other operating systems to see how they differ.

I think this behavior is probably highly operating system dependent.  The python
interpreter is assuming the OS will do something reasonably fair when it gives
up the global interpreter lock, but it looks like this isn't the case, at least
under Windows XP.  Still, it would be nice if something could be done to make
threading execution more fair, but I'm not sure how to do this without creating
some sort of scheduler in the python interpreter itself.

Is there anything which can be done?

Is the problem as bad under other operating systems?

Am I insane to try to do anything in the neighborhood of soft-realtime with
Python?

-- 
Matt Kimball
matt at kimball.net







More information about the Python-list mailing list