Skip to content

Instantly share code, notes, and snippets.

@j0hn
Created August 17, 2011 23:39
Show Gist options
  • Save j0hn/1152932 to your computer and use it in GitHub Desktop.
Save j0hn/1152932 to your computer and use it in GitHub Desktop.
Checkout models
#!/usr/bin/env python
# coding: utf-8
"""
Checkout queue test, a test between two models of queues on supermarkets
and banks and stuff like that.
The two models tested are:
Independent checkouts Single queue
--------------------- -----------
[C] | [C] | [C] [C] | [C] | [C]
o o o o o o
o o o _______ _______
o o o o
o o o o o
o o o -------
o o o o o o
----- o
o o o
In the independent model each checkout takes care of it queue but
in the single queue model each checkout takes care of the single queue
"""
import sys
import time
import random
import threading
DEFAULT_CHECKOUTS = 30
DEFAULT_PEOPLE_PER_CHECKOUT = 10
class IndependentCheckout(threading.Thread):
"""
Independent checkout, has an amount of persons that
it will be consumed eventually.
"""
def __init__(self, main_queue, amount):
"""
main_queue is the complete set of checkouts, when this checkout
has people it belongs to that set and does not belong when it's empty.
"""
threading.Thread.__init__(self)
self.queue = range(amount)
self.amount = amount
self.main_queue = main_queue
self.main_queue.append(self)
def pop(self):
rnd_time = random.uniform(0, 0.3)
time.sleep(rnd_time)
self.queue.pop()
def run(self):
while len(self.queue) > 0:
self.pop()
self.main_queue.remove(self)
class SingleCheckout(threading.Thread):
"""
A Single checkout that consumes people from the main queue.
Used to model the single queue checkout.
"""
def __init__(self, main_queue):
"""
mainQueu it's the unique queue that exists on the single model.
"""
threading.Thread.__init__(self)
self.main_queue = main_queue
def pop(self):
rnd_time = random.uniform(0, 0.3)
try:
self.main_queue.pop()
except IndexError:
return
time.sleep(rnd_time)
def run(self):
while len(self.main_queue) > 0:
self.pop()
def lazy_wait_until_empty(queue):
"""
Waits until queue it's empty waiting a short amount of time
between checks.
"""
while len(queue) > 0:
time.sleep(0.001)
def run_threaded():
"""
Runs the model with independent checkout and returns the
time that took to complete it.
"""
main_queue = []
for _ in range(CHECKOUTS):
checkout = IndependentCheckout(main_queue, PEOPLE_PER_CHECKOUT)
checkout.start()
start = time.time()
lazy_wait_until_empty(main_queue)
end = time.time()
return end - start
def run_single():
"""
Runs the model with a single queue and a lot of checkout that
consume people from the same queue. returns the
time that took to complete it.
"""
main_queue = range(CHECKOUTS * PEOPLE_PER_CHECKOUT)
for _ in range(CHECKOUTS):
checkout = SingleCheckout(main_queue)
checkout.start()
start = time.time()
lazy_wait_until_empty(main_queue)
end = time.time()
return end - start
if __name__ == "__main__":
if len(sys.argv) < 2 or "-h" in sys.argv or "--help" in sys.argv:
print "Usage: python %s METHOD [checkouts] [people_per_checkout]\n" % \
sys.argv[0]
print "METHOD can be Independent, Single or Both"
sys.exit(1)
method = sys.argv[1]
if len(sys.argv) > 3:
CHECKOUTS = int(sys.argv[2])
else:
CHECKOUTS = DEFAULT_CHECKOUTS
if len(sys.argv) > 4:
PEOPLE_PER_CHECKOUT = int(sys.argv[3])
else:
PEOPLE_PER_CHECKOUT = DEFAULT_PEOPLE_PER_CHECKOUT
if method.lower() == "independent" or method.lower() == "both":
print "Independent took: %.3f seconds" % run_threaded()
if method.lower() == "single" or method.lower() == "both":
print "Single took: %.3f seconds" % run_single()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment