[py-dev] new Channel callback

holger krekel hpk at trillke.net
Thu Apr 14 20:05:43 CEST 2005


Hi Jan, 

On Thu, Apr 14, 2005 at 19:17 +0200, Jan Balster wrote:
> holger krekel wrote:
> > On Thu, Apr 14, 2005 at 17:41 +0200, Jan Balster wrote:
> >>Hurray! It works. But it seems to me, using the callback is slower than
> >>receiving all items in a loop (13 secs vs. 15 secs).
> > 
> > That would be very odd.  Do you repeatedly get this? 
> > Btw, i'd recommend to add a test for exiting from a callback
> > because i am currently revising the threading mechanism :-) 
> Ok.
> 
> I did some benchmarking. Callback is faster than Loop, except for small
> numbers of received items.

Hum, i note that you are also measuring creation/teardown time. 
I've attached a modified benchmark script which avoids this, reusing
the same gateway all along.  There, for small number of elements, 
the behaviour is not completly consistent anymore (callback
sometimes wins).  

However, I don't currently care anyhow as callbacks are not
there for speed reasons but for convenience.  They might even
become slower when setting a callback would run that callback
in a separate thread which might make sense as a default
behaviour (otherwise you could block the receiver thread where
callbacks are currently run). 

In real life applications (like the tkinter frontend) the callback
gains you that you don't have to start a thread just to push 
an item from one queue to another. 

cheers, 

    holger


import py

remote_code = '''
    import sha
    number = channel.receive()
    for i in range(number):
        s = sha.new(str(i)).hexdigest() * 10
        channel.send(s)
'''

def use_callback(gw, number):
    channel = gw.newchannel()
    l = []
    channel.setcallback(l.append)
    channel.remote_exec(remote_code)
    channel.send(number)
    channel.waitclose(100.0)
    assert len(l) == number 

def use_loop(gw, number):
    channel = gw.newchannel()
    l = []
    channel.remote_exec(remote_code)
    channel.send(number)
    l = list(channel) 
    channel.waitclose(100.0)
    assert len(l) == number 

def test(gw, number):
    print
    print 'Receiving', number, 'elements'
    t1 = py.std.time.time()
    use_callback(gw, number)
    t1 = py.std.time.time() - t1
    print 'use_callback: \t%0.3f' % t1
    t2 = py.std.time.time()
    use_loop(gw, number)
    t2 = py.std.time.time() - t2
    print 'use_loop:  \t%0.3f' % t2
    print '*'* 20, 'The winner is',
    if t1 < t2:
        print 'Callback'
    else:
        print 'Loop'

if __name__ == '__main__':
    gw = py.execnet.PopenGateway(py.std.sys.executable)
    print "created gateway"
    for i in (10000, 2000, 1000, 100, 50, 10):
        test(gw, i)
    gw.exit() 



More information about the Pytest-dev mailing list