Real-Time Simulation with SimPy: Syncing with the Real World

<p>Normal SimPy runs as fast as possible. Simulation years pass in seconds. But sometimes you need simulation time to match real time.</p> <h2 id="when-to-use-real-time-simulation">When to Use Real-Time Simulation</h2> <ul> <li><strong>Live demonstrations</strong> - Show stakeholders the simulation running</li> <li><strong>Hardware-in-the-loop</strong> - Interface with real equipment</li> <li><strong>Training systems</strong> - Operators interact in real time</li> <li><strong>Testing</strong> - Validate timing-sensitive code</li> </ul> <h2 id="realtimeenvironment">RealtimeEnvironment</h2> <div class="code-block"><pre><span></span><code><span class="kn">import</span><span class="w"> </span><span class="nn">simpy.rt</span> <span class="n">env</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">rt</span><span class="o">.</span><span class="n">RealtimeEnvironment</span><span class="p">(</span><span class="n">factor</span><span class="o">=</span><span class="mf">1.0</span><span class="p">)</span> <span class="k">def</span><span class="w"> </span><span class="nf">process</span><span class="p">(</span><span class="n">env</span><span class="p">):</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Start at real time&quot;</span><span class="p">)</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span> <span class="c1"># Actually waits 5 seconds</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;5 seconds have passed&quot;</span><span class="p">)</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">process</span><span class="p">(</span><span class="n">env</span><span class="p">))</span> <span class="n">env</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">until</span><span class="o">=</span><span class="mi">10</span><span class="p">)</span> <span class="c1"># Takes 10 real seconds</span> </code></pre></div> <h2 id="speed-factor">Speed Factor</h2> <p>Control how fast simulation runs relative to real time:</p> <div class="code-block"><pre><span></span><code><span class="c1"># Real-time (1 sim second = 1 real second)</span> <span class="n">env</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">rt</span><span class="o">.</span><span class="n">RealtimeEnvironment</span><span class="p">(</span><span class="n">factor</span><span class="o">=</span><span class="mf">1.0</span><span class="p">)</span> <span class="c1"># Half speed (1 sim second = 2 real seconds)</span> <span class="n">env</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">rt</span><span class="o">.</span><span class="n">RealtimeEnvironment</span><span class="p">(</span><span class="n">factor</span><span class="o">=</span><span class="mf">0.5</span><span class="p">)</span> <span class="c1"># Double speed (1 sim second = 0.5 real seconds)</span> <span class="n">env</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">rt</span><span class="o">.</span><span class="n">RealtimeEnvironment</span><span class="p">(</span><span class="n">factor</span><span class="o">=</span><span class="mf">2.0</span><span class="p">)</span> <span class="c1"># 10x speed (1 sim second = 0.1 real seconds)</span> <span class="n">env</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">rt</span><span class="o">.</span><span class="n">RealtimeEnvironment</span><span class="p">(</span><span class="n">factor</span><span class="o">=</span><span class="mf">10.0</span><span class="p">)</span> </code></pre></div> <h2 id="strict-mode">Strict Mode</h2> <p>By default, SimPy tries to keep up with real time but doesn't guarantee it:</p> <div class="code-block"><pre><span></span><code><span class="c1"># Non-strict (default): proceeds even if behind schedule</span> <span class="n">env</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">rt</span><span class="o">.</span><span class="n">RealtimeEnvironment</span><span class="p">(</span><span class="n">factor</span><span class="o">=</span><span class="mf">1.0</span><span class="p">,</span> <span class="n">strict</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span> <span class="c1"># Strict: raises error if simulation can&#39;t keep up</span> <span class="n">env</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">rt</span><span class="o">.</span><span class="n">RealtimeEnvironment</span><span class="p">(</span><span class="n">factor</span><span class="o">=</span><span class="mf">1.0</span><span class="p">,</span> <span class="n">strict</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> </code></pre></div> <p>Use strict mode when timing accuracy is critical.</p> <h2 id="practical-example-traffic-light">Practical Example: Traffic Light</h2> <div class="code-block"><pre><span></span><code><span class="kn">import</span><span class="w"> </span><span class="nn">simpy.rt</span> <span class="kn">import</span><span class="w"> </span><span class="nn">time</span> <span class="k">def</span><span class="w"> </span><span class="nf">traffic_light</span><span class="p">(</span><span class="n">env</span><span class="p">):</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;[</span><span class="si">{</span><span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">&#39;%H:%M:%S&#39;</span><span class="p">)</span><span class="si">}</span><span class="s2">] GREEN&quot;</span><span class="p">)</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="mi">30</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;[</span><span class="si">{</span><span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">&#39;%H:%M:%S&#39;</span><span class="p">)</span><span class="si">}</span><span class="s2">] YELLOW&quot;</span><span class="p">)</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;[</span><span class="si">{</span><span class="n">time</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">&#39;%H:%M:%S&#39;</span><span class="p">)</span><span class="si">}</span><span class="s2">] RED&quot;</span><span class="p">)</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="mi">30</span><span class="p">)</span> <span class="n">env</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">rt</span><span class="o">.</span><span class="n">RealtimeEnvironment</span><span class="p">(</span><span class="n">factor</span><span class="o">=</span><span class="mf">1.0</span><span class="p">)</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">traffic_light</span><span class="p">(</span><span class="n">env</span><span class="p">))</span> <span class="n">env</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">until</span><span class="o">=</span><span class="mi">120</span><span class="p">)</span> <span class="c1"># Run for 2 minutes real time</span> </code></pre></div> <h2 id="interactive-simulation">Interactive Simulation</h2> <p>Accept user input during simulation:</p> <div class="code-block"><pre><span></span><code><span class="kn">import</span><span class="w"> </span><span class="nn">simpy.rt</span> <span class="kn">import</span><span class="w"> </span><span class="nn">threading</span> <span class="kn">import</span><span class="w"> </span><span class="nn">queue</span> <span class="n">command_queue</span> <span class="o">=</span> <span class="n">queue</span><span class="o">.</span><span class="n">Queue</span><span class="p">()</span> <span class="k">def</span><span class="w"> </span><span class="nf">user_input_thread</span><span class="p">():</span> <span class="w"> </span><span class="sd">&quot;&quot;&quot;Background thread for user input.&quot;&quot;&quot;</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="n">cmd</span> <span class="o">=</span> <span class="nb">input</span><span class="p">(</span><span class="s2">&quot;Enter command (add/quit): &quot;</span><span class="p">)</span> <span class="n">command_queue</span><span class="o">.</span><span class="n">put</span><span class="p">(</span><span class="n">cmd</span><span class="p">)</span> <span class="k">if</span> <span class="n">cmd</span> <span class="o">==</span> <span class="s1">&#39;quit&#39;</span><span class="p">:</span> <span class="k">break</span> <span class="k">def</span><span class="w"> </span><span class="nf">command_processor</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">server</span><span class="p">):</span> <span class="w"> </span><span class="sd">&quot;&quot;&quot;Process user commands.&quot;&quot;&quot;</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="mf">0.1</span><span class="p">)</span> <span class="c1"># Check every 0.1 sim seconds</span> <span class="k">try</span><span class="p">:</span> <span class="n">cmd</span> <span class="o">=</span> <span class="n">command_queue</span><span class="o">.</span><span class="n">get_nowait</span><span class="p">()</span> <span class="k">if</span> <span class="n">cmd</span> <span class="o">==</span> <span class="s1">&#39;add&#39;</span><span class="p">:</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">customer</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="sa">f</span><span class="s2">&quot;Manual-</span><span class="si">{</span><span class="n">env</span><span class="o">.</span><span class="n">now</span><span class="si">:</span><span class="s2">.1f</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">,</span> <span class="n">server</span><span class="p">))</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;Added customer at </span><span class="si">{</span><span class="n">env</span><span class="o">.</span><span class="n">now</span><span class="si">:</span><span class="s2">.1f</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span> <span class="k">elif</span> <span class="n">cmd</span> <span class="o">==</span> <span class="s1">&#39;quit&#39;</span><span class="p">:</span> <span class="k">return</span> <span class="k">except</span> <span class="n">queue</span><span class="o">.</span><span class="n">Empty</span><span class="p">:</span> <span class="k">pass</span> <span class="c1"># Start input thread</span> <span class="n">input_thread</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">user_input_thread</span><span class="p">,</span> <span class="n">daemon</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> <span class="n">input_thread</span><span class="o">.</span><span class="n">start</span><span class="p">()</span> <span class="n">env</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">rt</span><span class="o">.</span><span class="n">RealtimeEnvironment</span><span class="p">(</span><span class="n">factor</span><span class="o">=</span><span class="mf">1.0</span><span class="p">)</span> <span class="n">server</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">Resource</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">capacity</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">command_processor</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">server</span><span class="p">))</span> <span class="n">env</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">until</span><span class="o">=</span><span class="mi">300</span><span class="p">)</span> </code></pre></div> <h2 id="syncing-with-external-systems">Syncing with External Systems</h2> <p>Interface with real hardware or APIs:</p> <div class="code-block"><pre><span></span><code><span class="kn">import</span><span class="w"> </span><span class="nn">simpy.rt</span> <span class="kn">import</span><span class="w"> </span><span class="nn">requests</span> <span class="k">def</span><span class="w"> </span><span class="nf">external_data_fetcher</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">interval</span><span class="p">):</span> <span class="w"> </span><span class="sd">&quot;&quot;&quot;Fetch data from external API at regular intervals.&quot;&quot;&quot;</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="n">interval</span><span class="p">)</span> <span class="n">response</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">url</span><span class="p">)</span> <span class="n">data</span> <span class="o">=</span> <span class="n">response</span><span class="o">.</span><span class="n">json</span><span class="p">()</span> <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&quot;[</span><span class="si">{</span><span class="n">env</span><span class="o">.</span><span class="n">now</span><span class="si">}</span><span class="s2">] Fetched: </span><span class="si">{</span><span class="n">data</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span> <span class="c1"># Process data, update simulation state, etc.</span> <span class="n">env</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">rt</span><span class="o">.</span><span class="n">RealtimeEnvironment</span><span class="p">(</span><span class="n">factor</span><span class="o">=</span><span class="mf">1.0</span><span class="p">)</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">external_data_fetcher</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="s1">&#39;http://api.example.com/data&#39;</span><span class="p">,</span> <span class="mi">5</span><span class="p">))</span> <span class="n">env</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">until</span><span class="o">=</span><span class="mi">60</span><span class="p">)</span> </code></pre></div> <h2 id="visualisation-in-real-time">Visualisation in Real Time</h2> <p>Update a display as simulation runs:</p> <div class="code-block"><pre><span></span><code><span class="kn">import</span><span class="w"> </span><span class="nn">simpy.rt</span> <span class="kn">import</span><span class="w"> </span><span class="nn">matplotlib.pyplot</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="nn">plt</span> <span class="kn">from</span><span class="w"> </span><span class="nn">matplotlib.animation</span><span class="w"> </span><span class="kn">import</span> <span class="n">FuncAnimation</span> <span class="n">queue_lengths</span> <span class="o">=</span> <span class="p">[]</span> <span class="n">times</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">def</span><span class="w"> </span><span class="nf">monitor</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">server</span><span class="p">):</span> <span class="k">global</span> <span class="n">queue_lengths</span><span class="p">,</span> <span class="n">times</span> <span class="k">while</span> <span class="kc">True</span><span class="p">:</span> <span class="n">times</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">env</span><span class="o">.</span><span class="n">now</span><span class="p">)</span> <span class="n">queue_lengths</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">server</span><span class="o">.</span><span class="n">queue</span><span class="p">))</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="mf">0.5</span><span class="p">)</span> <span class="k">def</span><span class="w"> </span><span class="nf">animate</span><span class="p">(</span><span class="n">frame</span><span class="p">):</span> <span class="n">plt</span><span class="o">.</span><span class="n">cla</span><span class="p">()</span> <span class="n">plt</span><span class="o">.</span><span class="n">plot</span><span class="p">(</span><span class="n">times</span><span class="p">,</span> <span class="n">queue_lengths</span><span class="p">)</span> <span class="n">plt</span><span class="o">.</span><span class="n">xlabel</span><span class="p">(</span><span class="s1">&#39;Time&#39;</span><span class="p">)</span> <span class="n">plt</span><span class="o">.</span><span class="n">ylabel</span><span class="p">(</span><span class="s1">&#39;Queue Length&#39;</span><span class="p">)</span> <span class="n">plt</span><span class="o">.</span><span class="n">title</span><span class="p">(</span><span class="s1">&#39;Real-Time Queue Monitor&#39;</span><span class="p">)</span> <span class="c1"># Setup</span> <span class="n">env</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">rt</span><span class="o">.</span><span class="n">RealtimeEnvironment</span><span class="p">(</span><span class="n">factor</span><span class="o">=</span><span class="mf">1.0</span><span class="p">)</span> <span class="n">server</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">Resource</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">capacity</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">arrivals</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">server</span><span class="p">))</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">monitor</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">server</span><span class="p">))</span> <span class="c1"># Animation</span> <span class="n">fig</span> <span class="o">=</span> <span class="n">plt</span><span class="o">.</span><span class="n">figure</span><span class="p">()</span> <span class="n">ani</span> <span class="o">=</span> <span class="n">FuncAnimation</span><span class="p">(</span><span class="n">fig</span><span class="p">,</span> <span class="n">animate</span><span class="p">,</span> <span class="n">interval</span><span class="o">=</span><span class="mi">500</span><span class="p">)</span> <span class="c1"># Update every 500ms</span> <span class="c1"># Run simulation in background thread</span> <span class="kn">import</span><span class="w"> </span><span class="nn">threading</span> <span class="n">sim_thread</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="k">lambda</span><span class="p">:</span> <span class="n">env</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">until</span><span class="o">=</span><span class="mi">60</span><span class="p">))</span> <span class="n">sim_thread</span><span class="o">.</span><span class="n">start</span><span class="p">()</span> <span class="n">plt</span><span class="o">.</span><span class="n">show</span><span class="p">()</span> </code></pre></div> <h2 id="logging-with-real-timestamps">Logging with Real Timestamps</h2> <div class="code-block"><pre><span></span><code><span class="kn">import</span><span class="w"> </span><span class="nn">simpy.rt</span> <span class="kn">import</span><span class="w"> </span><span class="nn">logging</span> <span class="kn">import</span><span class="w"> </span><span class="nn">time</span> <span class="n">logging</span><span class="o">.</span><span class="n">basicConfig</span><span class="p">(</span> <span class="n">level</span><span class="o">=</span><span class="n">logging</span><span class="o">.</span><span class="n">INFO</span><span class="p">,</span> <span class="nb">format</span><span class="o">=</span><span class="s1">&#39;</span><span class="si">%(asctime)s</span><span class="s1"> | sim_t=</span><span class="si">%(sim_time)s</span><span class="s1"> | </span><span class="si">%(message)s</span><span class="s1">&#39;</span> <span class="p">)</span> <span class="k">class</span><span class="w"> </span><span class="nc">SimTimeFilter</span><span class="p">(</span><span class="n">logging</span><span class="o">.</span><span class="n">Filter</span><span class="p">):</span> <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">env</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">env</span> <span class="o">=</span> <span class="n">env</span> <span class="k">def</span><span class="w"> </span><span class="nf">filter</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">record</span><span class="p">):</span> <span class="n">record</span><span class="o">.</span><span class="n">sim_time</span> <span class="o">=</span> <span class="sa">f</span><span class="s2">&quot;</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">now</span><span class="si">:</span><span class="s2">.2f</span><span class="si">}</span><span class="s2">&quot;</span> <span class="k">return</span> <span class="kc">True</span> <span class="n">env</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">rt</span><span class="o">.</span><span class="n">RealtimeEnvironment</span><span class="p">(</span><span class="n">factor</span><span class="o">=</span><span class="mf">1.0</span><span class="p">)</span> <span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">()</span> <span class="n">logger</span><span class="o">.</span><span class="n">addFilter</span><span class="p">(</span><span class="n">SimTimeFilter</span><span class="p">(</span><span class="n">env</span><span class="p">))</span> <span class="k">def</span><span class="w"> </span><span class="nf">process</span><span class="p">(</span><span class="n">env</span><span class="p">):</span> <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&quot;Process started&quot;</span><span class="p">)</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span> <span class="n">logger</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s2">&quot;Process completed&quot;</span><span class="p">)</span> </code></pre></div> <h2 id="performance-considerations">Performance Considerations</h2> <p>Real-time simulation has constraints:</p> <div class="code-block"><pre><span></span><code><span class="c1"># Bad: Complex computation blocks real-time sync</span> <span class="k">def</span><span class="w"> </span><span class="nf">slow_process</span><span class="p">(</span><span class="n">env</span><span class="p">):</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="n">result</span> <span class="o">=</span> <span class="n">very_slow_computation</span><span class="p">()</span> <span class="c1"># Takes 3 real seconds</span> <span class="c1"># Now we&#39;re behind schedule!</span> <span class="c1"># Better: Offload heavy computation</span> <span class="kn">import</span><span class="w"> </span><span class="nn">concurrent.futures</span> <span class="n">executor</span> <span class="o">=</span> <span class="n">concurrent</span><span class="o">.</span><span class="n">futures</span><span class="o">.</span><span class="n">ThreadPoolExecutor</span><span class="p">()</span> <span class="k">def</span><span class="w"> </span><span class="nf">async_process</span><span class="p">(</span><span class="n">env</span><span class="p">):</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="n">future</span> <span class="o">=</span> <span class="n">executor</span><span class="o">.</span><span class="n">submit</span><span class="p">(</span><span class="n">very_slow_computation</span><span class="p">)</span> <span class="c1"># Continue simulation while computation runs</span> </code></pre></div> <h2 id="switching-between-modes">Switching Between Modes</h2> <p>Same model, different execution:</p> <div class="code-block"><pre><span></span><code><span class="k">def</span><span class="w"> </span><span class="nf">create_simulation</span><span class="p">(</span><span class="n">realtime</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">factor</span><span class="o">=</span><span class="mf">1.0</span><span class="p">):</span> <span class="k">if</span> <span class="n">realtime</span><span class="p">:</span> <span class="n">env</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">rt</span><span class="o">.</span><span class="n">RealtimeEnvironment</span><span class="p">(</span><span class="n">factor</span><span class="o">=</span><span class="n">factor</span><span class="p">)</span> <span class="k">else</span><span class="p">:</span> <span class="n">env</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">Environment</span><span class="p">()</span> <span class="c1"># Setup simulation (same code either way)</span> <span class="n">server</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">Resource</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">capacity</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span> <span class="n">env</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">arrivals</span><span class="p">(</span><span class="n">env</span><span class="p">,</span> <span class="n">server</span><span class="p">))</span> <span class="k">return</span> <span class="n">env</span> <span class="c1"># Fast simulation for analysis</span> <span class="n">env</span> <span class="o">=</span> <span class="n">create_simulation</span><span class="p">(</span><span class="n">realtime</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span> <span class="n">env</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">until</span><span class="o">=</span><span class="mi">10000</span><span class="p">)</span> <span class="c1"># Real-time for demonstration</span> <span class="n">env</span> <span class="o">=</span> <span class="n">create_simulation</span><span class="p">(</span><span class="n">realtime</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">factor</span><span class="o">=</span><span class="mf">1.0</span><span class="p">)</span> <span class="n">env</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="n">until</span><span class="o">=</span><span class="mi">60</span><span class="p">)</span> </code></pre></div> <h2 id="gotchas">Gotchas</h2> <h3 id="simulation-falling-behind">Simulation Falling Behind</h3> <div class="code-block"><pre><span></span><code><span class="c1"># With strict=True, this raises an error if can&#39;t keep up</span> <span class="n">env</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">rt</span><span class="o">.</span><span class="n">RealtimeEnvironment</span><span class="p">(</span><span class="n">factor</span><span class="o">=</span><span class="mf">1.0</span><span class="p">,</span> <span class="n">strict</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span> <span class="c1"># With strict=False, simulation proceeds but timing drifts</span> <span class="n">env</span> <span class="o">=</span> <span class="n">simpy</span><span class="o">.</span><span class="n">rt</span><span class="o">.</span><span class="n">RealtimeEnvironment</span><span class="p">(</span><span class="n">factor</span><span class="o">=</span><span class="mf">1.0</span><span class="p">,</span> <span class="n">strict</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span> </code></pre></div> <h3 id="blocking-operations">Blocking Operations</h3> <div class="code-block"><pre><span></span><code><span class="c1"># Don&#39;t do this - blocks the simulation</span> <span class="k">def</span><span class="w"> </span><span class="nf">bad_process</span><span class="p">(</span><span class="n">env</span><span class="p">):</span> <span class="kn">import</span><span class="w"> </span><span class="nn">time</span> <span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span> <span class="c1"># Blocks everything!</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="c1"># Use simulation timeout instead</span> <span class="k">def</span><span class="w"> </span><span class="nf">good_process</span><span class="p">(</span><span class="n">env</span><span class="p">):</span> <span class="k">yield</span> <span class="n">env</span><span class="o">.</span><span class="n">timeout</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span> <span class="c1"># Proper simulation delay</span> </code></pre></div> <h2 id="summary">Summary</h2> <p>Real-time simulation: - Use <code>simpy.rt.RealtimeEnvironment</code> - Control speed with <code>factor</code> - Use <code>strict=True</code> when timing matters - Avoid blocking operations - Good for demos, testing, hardware integration</p> <p>Sometimes you need to slow down to see what's happening.</p> <h2 id="next-steps">Next Steps</h2> <ul> <li><a href="/blog_posts/simpy-environment-explained.html">SimPy Environment Explained</a></li> <li><a href="/blog_posts/simpy-visualize-results.html">Visualising Results</a></li> <li><a href="/blog_posts/simpy-logging.html">Logging in SimPy</a></li> </ul>

Discover the Power of Simulation

Want to become a go-to expert in simulation with Python? The Complete Simulation Bootcamp will show you how simulation can transform your career and your projects.

Explore the Bootcamp