Sturla Molden skrev:

However, David Beazley is not talking about Windows. Since the GIL is apparently not a mutex on Windows, it could behave differently. So I wrote a small script that contructs a GIL battle, and record how often a check-interval results in a thread-switch or not. For monitoring check intervals, I used a small C extension to read _Py_Ticker from ceval.c. It is not declared static so I could easily hack into it.

Anyway, if anyone wants to run a GIL battle, here is the code I used.

If it turns out the GIL is far worse with pthreads, as it is implemented with a mutex, it might be a good idea to reimplement it with an event object as it is on Windows.

Sturla Molden

----------------

In python:

from giltest import *
from time import clock
import threading
import sys


def thread(rank, battle, start):

   while not start.isSet():
       if rank == 0:
           start.set()

   try:
       while 1:
           battle.record(rank)
   except:
pass

if __name__ == '__main__':

   sys.setcheckinterval(1000)

   print "check interval = %d" % sys.getcheckinterval()

   for nthreads  in range(1,7):
start = threading.Event()
       battle = GIL_Battle(100000)
       threads = [threading.Thread(target=thread, args=(i,battle,start))
                   for i in range(1,nthreads)]
       for t in threads:
           t.setDaemon(True)
           t.start()

       thread(0, battle, start)
       for t in threads: t.join()
s,m = battle.report() print "nthreads=%d, swiched=%d, missed=%d" % (nthreads, s, m)


In Cython or Pyrex:


from exceptions import Exception

cdef extern from *:
   ctypedef int vint "volatile int"
   vint _Py_Ticker

class StopBattle(Exception):
   pass

cdef class GIL_Battle:

   """ tests the fairness of the GIL """

   cdef vint prev_tick, prev_rank, switched, missed
   cdef int trials
def __cinit__(GIL_Battle self, int trials=100000):
       self.prev_tick = _Py_Ticker
       self.prev_rank = -1
       self.missed = 0
       self.switched = 0
       self.trials = trials

   def record(GIL_Battle self, int rank):
       if self.trials == self.switched + self.missed:
raise StopBattle if self.prev_rank == -1:
           self.prev_tick = _Py_Ticker
           self.prev_rank = rank
       else:
           if _Py_Ticker > self.prev_tick:
               if self.prev_rank == rank:
                   self.missed += 1
               else:
                   self.switched += 1
               self.prev_tick = _Py_Ticker
               self.prev_rank = rank
           else:
               self.prev_tick = _Py_Ticker
def report(GIL_Battle self):
       return int(self.switched), int(self.missed)








_______________________________________________
Python-Dev mailing list
Python-Dev@python.org
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com

Reply via email to