[Zope] fairness of request processing

Daniel Mahler mahler@cyc.com
Mon, 8 Jul 2002 03:51:23 -0500


here is another variant of the minimal product::
  
    from time import sleep, clock, time
    from threading import *
    
    from OFS import SimpleItem
    
    lock = Lock()
    
    condition = Condition()
    
    class minimal(SimpleItem.SimpleItem, Thread):
    
    	"minimal object"
    
    	meta_type = 'minimal'
    
    	manage_options = (
    	    {'label': 'View', 'action': 'index_html'},
    	)
    
    	
    	def __init__(self, id):
    	    "initialise a new instance of Minimal"
    	    self.id = id
    
    	def index_html(self):
    	    "used to view content of the object"
    	    time1 = time()
    	    lock.acquire()
    	    time2 = time()
    	    sleep(2)
    	    time3 = time()
    	    lock.release()
    	    time4 = time()
    	    return '%s\t%s\t%s\t%s'%(time1,time2,time3,time4)
    	    
    	
    	def manage_addMinimal(self, id, RESPONSE=None):
    	    "Add a Minimal to a folder."
    	    self._setObject(id, minimal(id))
    	    RESPONSE.redirect('index_html')
    		
    	def manage_addMinimalForm(self):
    	    "The form used to get the instance' id from the user."
    	    return """<html>
    <body>
    Please type the id of the minimal instance:<br>
    <form name="form" action="manage_addMinimal"><br>
    <input type="text" name="id"><br>
    <input type="submit" value="add">
    </form>
    </body>
    </html>"""

The test below makes it seem that when hit with a batch of requests,
the first 4 request get the 4 worker threads,
with 3 waiting on the lock, but when the 1st thread releases the lock,
it starts processing another request and reacquires the lock
before the other three threads manage to wake up.
So the other 3 threads are starved and the first thread processes the
bulk of the requests.

I hit Zope from a client with::

   for i in range(20): Thread(target = retrieve).start()

and get back::

    200
    1026117262.34	1026117262.34	1026117264.33	1026117264.33
    200
    1026117264.34	1026117264.34	1026117266.33	1026117266.33
    200
    1026117266.34	1026117266.34	1026117268.33	1026117268.33
    200
    1026117268.34	1026117268.34	1026117270.33	1026117270.33
    200
    1026117270.34	1026117270.34	1026117272.33	1026117272.33
    200
    1026117272.34	1026117272.34	1026117274.33	1026117274.33
    200
    1026117274.34	1026117274.34	1026117276.33	1026117276.33
    200
    1026117276.34	1026117276.34	1026117278.33	1026117278.33
    200
    1026117278.34	1026117278.34	1026117280.33	1026117280.33
    200
    1026117280.34	1026117280.34	1026117282.33	1026117282.33
    200
    1026117282.34	1026117282.34	1026117284.33	1026117284.33
    200
    1026117284.34	1026117284.34	1026117286.33	1026117286.33
    200
    1026117286.34	1026117286.34	1026117288.33	1026117288.33
    200
    1026117288.34	1026117288.34	1026117290.33	1026117290.33
    200
    1026117290.34	1026117290.34	1026117292.33	1026117292.33
    200
    1026117292.34	1026117292.34	1026117294.33	1026117294.33
    200
    1026117294.34	1026117294.34	1026117296.33	1026117296.33
    200
    1026117262.35	1026117296.35	1026117298.34	1026117298.34
    200
    1026117262.35	1026117298.35	1026117300.35	1026117300.35
    200
    1026117262.34	1026117300.36	1026117302.36	1026117302.36

I can reproduce this beahviour reliably.
I am using Zope-2.5.1, with python-2.1.3 under linux.

Daniel