efficient idiomatic queue?
Delaney, Timothy
tdelaney at avaya.com
Wed Jan 16 20:57:58 EST 2002
> From: David Eppstein [mailto:eppstein at ics.uci.edu]
>
> In article <mailman.1011223225.3777.python-list at python.org>,
> "Delaney, Timothy" <tdelaney at avaya.com> wrote:
>
> > So, it looks like there is a definite speed penalty with
> the dict versions,
> > although the majority of that is probably namespace lookup
> time (more
> > operations). A C version would probably do quite well.
>
> It's good to see actual data, but I don't think this is a
> fair comparison:
> your queues always have at most one item in them, so you
> never see how well
> these versions scale to different lengths. Try replacing
Remind me to hit myself with a rubber chicken ...
Of course I completely invalidated the point of the entire exercise ... I
should have added all, then removed all (which in my mind I was doing). And
my comparison with list/array is incorrect as well ... I needed to change
every pop() to accept a position (and ignore it :) so I could pop(0) on the
list and array.
import time
import string
import array
class DictIntFifo:
def __init__(self):
self.data = {}
self.nextin = 0
self.nextout = 0
def append(self, value):
self.data[self.nextin] = value
try:
self.nextin += 1
except OverflowError:
self.nextin += long(1)
def pop(self, pos=-1):
value = self.data[self.nextout]
del self.data[self.nextout]
try:
self.nextout += 1
except OverflowError:
self.nextout += long(1)
return value
class DictLongFifo:
def __init__(self):
self.data = {}
self.nextin = long(0)
self.nextout = long(0)
def append(self, value):
self.data[self.nextin] = value
self.nextin += 1
def pop(self, pos=-1):
value = self.data[self.nextout]
del self.data[self.nextout]
self.nextout += 1
return value
class ListPrependFifo:
""""""
def __init__(self):
""""""
self.data = []
def append(self, value):
self.data.insert(0, value)
def pop(self, pos=-1):
return self.data.pop()
class ListAppendFifo:
""""""
def __init__(self):
""""""
self.data = []
def append(self, value):
self.data.append(value)
def pop(self, pos=-1):
return self.data.pop(0)
def test (fifo, iterations):
""""""
start = time.clock()
for i in xrange(iterations):
fifo.append(i)
for i in xrange(iterations):
j = fifo.pop(0)
end = time.clock()
try:
name = fifo.__class__.__name__
except:
name = type(fifo)
print "%-8s %-20s %-06f" % (iterations, name, end - start,)
for i in xrange(3):
print
test([], 10**(i + 3))
test(array.array('i'), 10**(i + 3))
test(DictIntFifo(), 10**(i + 3))
test(DictLongFifo(), 10**(i + 3))
test(ListPrependFifo(), 10**(i + 3))
test(ListAppendFifo(), 10**(i + 3))
---------- Run ----------
1000 <type 'list'> 0.007721
1000 <type 'array'> 0.007273
1000 DictIntFifo 0.012430
1000 DictLongFifo 0.017795
1000 ListPrependFifo 0.013849
1000 ListAppendFifo 0.014851
10000 <type 'list'> 0.329070
10000 <type 'array'> 0.234557
10000 DictIntFifo 0.123809
10000 DictLongFifo 0.185284
10000 ListPrependFifo 0.329698
10000 ListAppendFifo 0.398269
100000 <type 'list'> 76.195043
100000 <type 'array'> 56.828019
100000 DictIntFifo 1.269020
100000 DictLongFifo 1.961017
100000 ListPrependFifo 60.693928
100000 ListAppendFifo 77.094517
So once you get to decently large quantities in the queue, the dict versions
make real sense over a basic list (Win2000).
Tim Delaney
More information about the Python-list
mailing list