[Python-Dev] GIL behaviour under Windows

Sturla Molden sturla at molden.no
Thu Oct 22 05:09:44 CEST 2009


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)





 




More information about the Python-Dev mailing list