import Queue
import threading
class BackgroundGenerator(threading.Thread):
def __init__(self, generator, lookahead=10):
threading.Thread.__init__(self)
self.queue = Queue.Queue(lookahead)
self.generator = generator
self.daemon = True
self.start()
def __iter__(self):
return self
def run(self):
for item in self.generator:
self.queue.put(item)
self.queue.put(None)
def next(self):
next_item = self.queue.get()
if next_item is None:
raise StopIteration
return next_item
def test():
import time
def processing_releasing_GIL(process_time):
# simulating processing that releases the Global Interpreter Lock
# also see: https://wiki.python.org/moin/GlobalInterpreterLock
time.sleep(process_time)
def processing_no_release_GIL(n):
i = 0
while i < n:
i += 1
def generator_count_up_release_GIL(count, process_time):
x = 1
while x <= count:
yield x
processing_releasing_GIL(process_time)
x += 1
def generator_count_up_not_releasing_GIL(count, n):
x = 1
while x <= count:
yield x
processing_no_release_GIL(n)
x += 1
print "Testing runtime of a generator that releases the GIL."
n = 10
# test runtime without backgroundGenerator
start = time.time()
gen1 = generator_count_up_release_GIL(n, 0.1)
counter = 0
for i in gen1:
counter = i
processing_releasing_GIL(0.1)
print "- no BackgroundGenerator: ", counter, time.time() - start
# test runtime WITH backgroundGenerator
start = time.time()
gen2 = BackgroundGenerator(generator_count_up_release_GIL(n, 0.1))
counter = 0
for i in gen2:
counter = i
processing_releasing_GIL(0.1)
print "- with BackgroundGenerator:", counter, time.time() - start
print "Testing runtime of a generator that does not release the GIL."
iterations = 2000000
# test runtime without backgroundGenerator
start = time.time()
gen1 = generator_count_up_not_releasing_GIL(n, iterations)
counter = 0
for i in gen1:
counter = i
processing_no_release_GIL(iterations)
print "- no BackgroundGenerator: ", counter, time.time() - start
# test runtime WITH backgroundGenerator
start = time.time()
gen2 = BackgroundGenerator(generator_count_up_not_releasing_GIL(n, iterations))
counter = 0
for i in gen2:
counter = i
processing_no_release_GIL(iterations)
print "- with BackgroundGenerator:", counter, time.time() - start
if __name__=="__main__":
test()