예제 #1
0
    def _agent_accepting_travelers(self, name) -> None:
        agent = Resource(1)  # Models how the agent is busy processing a traveler.
        while True:
            # Are we on break yet? That coffee won't drink itself.
            self._agents_working.wait()
            info(f"Agent {name}/{self.num} ready")

            # Is anybody in there?
            if self._travelers_waiting.is_empty():
                debug(f"Agent {name}/{self.num} waiting for travelers")
                self._traveler_ready.turn_off().wait()
                continue  # Check back if we've gone on break while waiting for somebody.

            # Accept the next traveler traversing the checkpoint.
            traveler_next = self._travelers_waiting.peek()
            debug(f"Agent {name}/{self.num} about to process traveler {traveler_next.local.name}")
            traveler_next.local.agent = agent
            traveler_next.local.agent_name = f"{name}/{self.num}"
            self._travelers_waiting.pop()

            # Allow the next traveler to "use" this agent, so we may then wait until it's done traversing.
            advance(0.0)
            debug(f"Agent {name}/{self.num} doing the processing.")
            with agent.using():
                debug(f"Agent {name}/{self.num} done with the processing.")
예제 #2
0
def test_auto_log_resource_take_again(auto_logger):
    def process(res):
        local.name = "proc"
        res.take(2)
        advance(10)
        res.take(3)
        advance(10)
        res.release(5)

    sim = Simulator(name="sim")
    resource = Resource(5, name="res")
    sim.add(process, resource)
    sim.run()

    check_log(
        auto_logger, (logging.INFO, 0.0, "", "Simulator", "sim", "add",
                      dict(fn=process, args=(resource, ), kwargs={})),
        (logging.INFO, 0.0, "", "Simulator", "sim", "run", dict(duration=inf)),
        (logging.INFO, 0.0, "proc", "Resource", "res", "take",
         dict(num_instances=2, free=5)), (logging.INFO, 0.0, "proc", "Process",
                                          "proc", "advance", dict(delay=10.0)),
        (logging.INFO, 10.0, "proc", "Resource", "res", "take",
         dict(num_instances=3, free=3)),
        (logging.WARNING, 10.0, "proc", "Resource", "res", "take-again",
         dict(already=2, more=3)), (logging.INFO, 10.0, "proc", "Process",
                                    "proc", "advance", dict(delay=10.0)),
        (logging.INFO, 20.0, "proc", "Resource", "res", "release",
         dict(num_instances=5, keeping=0, free=5)),
        (logging.INFO, 20.0, "proc", "Process", "proc", "die-finish", {}),
        (logging.INFO, 20.0, "", "Simulator", "sim", "stop", {}))
예제 #3
0
def run_resource_test_incoherent(num_take: int, num_release: int):
    sim = Simulator()
    resource = Resource(5)
    sim.add(take_M_release_N, resource, num_take, num_release)
    with pytest.raises(ValueError):
        sim.run()
        assert resource.num_instances_free >= 0
        assert resource.num_instances_total == 5
예제 #4
0
def run_test_resource(resource_taker: ResourceTaker, num_instances: int,
                      expected: List[float]) -> None:
    sim = Simulator()
    resource = Resource(num_instances)
    log: List[float] = []
    for n in range(8):
        sim.add(resource_taker, resource, float(n + 1), log)
    sim.run()
    assert expected == pytest.approx(log)
예제 #5
0
def test_resource_release_while_holding_none():
    def proc(resource: Resource) -> None:
        resource.release()
        pytest.fail()

    sim = Simulator()
    resource = Resource(1)
    sim.add(proc, resource)
    with pytest.raises(RuntimeError):
        sim.run()
예제 #6
0
def test_resource_timeout():
    resource = Resource(1)
    log = []

    def take_but_balk(name, delay_balk):
        try:
            with resource.using(timeout=delay_balk):
                advance(20.0)
                log.append((name, "finish"))
        except Timeout:
            log.append((name, "balk"))

    sim = Simulator()
    sim.add(take_but_balk, "a", 10.0)
    sim.add_in(5.0, take_but_balk, "b", 10.0)
    sim.run()
    assert log == [("b", "balk"), ("a", "finish")]
예제 #7
0
def test_log_additional_fields(logger):
    def ordeal(queue, signal, resource):
        logger.debug("debug")
        advance(10)
        logger.info("info")
        pause()
        logger.warning("warning")
        queue.join()
        logger.error("error", extra=dict(sim_process="the-process"))
        signal.wait()
        logger.critical("critical")
        resource.take()
        advance(10)
        logger.critical("finish", extra=dict(sim_time=1000.0))
        resource.release()

    def do_resume(proc_ordeal):
        advance(15)
        proc_ordeal.resume()

    def do_pop(queue):
        advance(30)
        queue.pop()

    def do_open(signal):
        advance(50)
        signal.turn_on()

    sim = Simulator()
    queue = Queue()
    signal = Signal().turn_off()
    resource = Resource(1)
    proc_ordeal = sim.add(ordeal, queue, signal, resource)
    name_ordeal = proc_ordeal.local.name
    sim.add(do_resume, proc_ordeal)
    sim.add(do_pop, queue)
    sim.add(do_open, signal)
    sim.run()

    assert [(logging.DEBUG, 0.0, name_ordeal, "debug"),
            (logging.INFO, 10.0, name_ordeal, "info"),
            (logging.WARNING, 15.0, name_ordeal, "warning"),
            (logging.ERROR, 30.0, "the-process", "error"),
            (logging.CRITICAL, 50.0, name_ordeal, "critical"),
            (logging.CRITICAL, 1000.0, name_ordeal, "finish")
            ] == logger.handlers[0].log
예제 #8
0
def test_auto_log_resource(auto_logger):
    def proc(res, name, delay_before, delay_with):
        local.name = name
        advance(delay_before)
        with res.using():
            advance(delay_with)

    resource = Resource(1, name="the-resource")
    sim = Simulator(name="sim")
    sim.add(proc, resource, "alpha", 10, 50)
    sim.add(proc, resource, "beta", 30, 10)
    sim.run()

    check_log(
        auto_logger,
        (logging.INFO, 0.0, "", "Simulator", "sim", "add",
         dict(fn=proc, args=(resource, "alpha", 10.0, 50.0), kwargs={})),
        (logging.INFO, 0.0, "", "Simulator", "sim", "add",
         dict(fn=proc, args=(resource, "beta", 30.0, 10.0), kwargs={})),
        (logging.INFO, 0.0, "", "Simulator", "sim", "run", dict(duration=inf)),
        (logging.INFO, 0.0, "alpha", "Process", "alpha", "advance",
         dict(delay=10.0)), (logging.INFO, 0.0, "beta", "Process", "beta",
                             "advance", dict(delay=30.0)),
        (logging.INFO, 10.0, "alpha", "Resource", "the-resource", "take",
         dict(num_instances=1, free=1)),
        (logging.INFO, 10.0, "alpha", "Process", "alpha", "advance",
         dict(delay=50.0)),
        (logging.INFO, 30.0, "beta", "Resource", "the-resource", "take",
         dict(num_instances=1, free=0)), (logging.INFO, 30.0, "beta", "Queue",
                                          "the-resource-queue", "join", {}),
        (logging.INFO, 30.0, "beta", "Process", "beta", "pause", {}),
        (logging.INFO, 60.0, "alpha", "Resource", "the-resource", "release",
         dict(num_instances=1, keeping=0, free=1)),
        (logging.INFO, 60.0, "alpha", "Queue", "the-resource-queue", "pop",
         dict(process="beta")),
        (logging.INFO, 60.0, "alpha", "Process", "beta", "resume", {}),
        (logging.INFO, 60.0, "alpha", "Process", "alpha", "die-finish", {}),
        (logging.INFO, 60.0, "beta", "Process", "beta", "advance",
         dict(delay=10.0)),
        (logging.INFO, 70.0, "beta", "Resource", "the-resource", "release",
         dict(num_instances=1, keeping=0, free=1)),
        (logging.INFO, 70.0, "beta", "Process", "beta", "die-finish", {}),
        (logging.INFO, 70.0, "", "Simulator", "sim", "stop", {}))
예제 #9
0
 def proc(resource: Resource) -> None:
     resource.release()
     pytest.fail()
예제 #10
0
def take_M_release_N(resource: Resource, num_take: int,
                     num_release: int) -> None:
    resource.take(num_take)
    advance(1.0)
    resource.release(num_release)
예제 #11
0
def take_many(resource: Resource, delay: float, log: List[float]) -> None:
    with resource.using(int(delay)):
        do_while_holding_resource(delay, log)
예제 #12
0
def take_release(resource: Resource, delay: float, log: List[float]) -> None:
    resource.take()
    do_while_holding_resource(delay, log)
    resource.release()
예제 #13
0
from random import Random

from greensim import Simulator, advance, add, Resource, now
from greensim.progress import track_progress

# Time convention: 1.0 == 1 minute

# Initial setup.
rng = Random()
sim = Simulator()
resource = Resource(1)  # One server for the queue.

# Rates of customer arrival and service.
RATE_ARRIVAL = 1.0 / 10.0
RATE_SERVICE = 1.0 / 6.0

# Simulation runs until a certain number of customers have been served.
num_served = 0
NUM_CLIENTS_STOP = 200000

# Measure total time spent in the system (the *service time*).
times_service = []


# Arrival process: start the service of another customer according to a Poisson process. In other words, arrival time
# between customers is an exponential random variable of mean the inverse of the arrival rate. The Random class'
# expovariate takes the inverse of the intended mean as parameter.
def arrival():
    while True:
        advance(rng.expovariate(RATE_ARRIVAL))
        add(service)