Sometimes, you might not want to perform a simulation as fast as possible but synchronous to the wall-clock time. This kind of simulation is also called real-time simulation.
Real-time simulations may be necessary
To convert a simulation into a real-time simulation, you only need to replace SimPy’s default Environment with a simpy.rt.RealtimeEnvironment. Apart from the initial_time argument, there are two additional parameters: factor and strict: RealtimeEnvironment(initial_time=0, factor=1.0, strict=True).
The factor defines how much real time passes with each step of simulation time. By default, this is one second. If you set factor=0.1, a unit of simulation time will only take a tenth of a second; if you set factor=60, it will take a minute.
Here is a simple example for converting a normal simulation to a real-time simulation with a duration of one tenth of a second per simulation time unit:
>>> import time
>>> import simpy
>>>
>>> def example(env):
... start = time.perf_counter()
... yield env.timeout(1)
... end = time.perf_counter()
... print('Duration of one simulation time unit: %.2fs' % (end - start))
>>>
>>> env = simpy.Environment()
>>> proc = env.process(example(env))
>>> env.run(until=proc)
Duration of one simulation time unit: 0.00s
>>>
>>> import simpy.rt
>>> env = simpy.rt.RealtimeEnvironment(factor=0.1)
>>> proc = env.process(example(env))
>>> env.run(until=proc)
Duration of one simulation time unit: 0.10s
If the strict parameter is set to True (the default), the step() and run() methods will raise a RuntimeError if the computation within a simulation time step take more time than the real-time factor allows. In the following example, a process will perform a task that takes 0.02 seconds within a real-time environment with a time factor of 0.01 seconds:
>>> import time
>>> import simpy.rt
>>>
>>> def slow_proc(env):
... time.sleep(0.02) # Heavy computation :-)
... yield env.timeout(1)
>>>
>>> env = simpy.rt.RealtimeEnvironment(factor=0.01)
>>> proc = env.process(slow_proc(env))
>>> try:
... env.run(until=proc)
... print('Everything alright')
... except RuntimeError:
... print('Simulation is too slow')
Simulation is too slow
To suppress the error, simply set strict=False:
>>> env = simpy.rt.RealtimeEnvironment(factor=0.01, strict=False)
>>> proc = env.process(slow_proc(env))
>>> try:
... env.run(until=proc)
... print('Everything alright')
... except RuntimeError:
... print('Simulation is too slow')
Everything alright
That’s it. Real-time simulations are that simple with SimPy!