Reusing/Resetting SimPy Models with Different Environments

55 views
Skip to first unread message

henrikw

unread,
May 22, 2025, 7:35:54 AMMay 22
to python-simpy

Hi everyone,

I'm working on a simulation of a production process using SimPy, and I'm currently trying to optimize certain parameters through multiple simulation runs. For each run, I use different parameter values, which requires me to reset the simulation environment (simpy.Environment) each time.

Right now, I'm rebuilding the entire model from scratch for every simulation using a function like build_model(env)where I pass in a fresh environment. However, since my model is quite complex, rebuilding it repeatedly becomes a performance bottleneck. I would like to reuse the model structure and just reset the environment, or at least avoid having to fully reconstruct all components each time.

Has anyone found a good way to "recycle" or reuse an existing model while resetting the environment? Is there a way to replace or rebind environment-dependent methods (like process generators) to a new environment without reinitializing everything?

Here’s a simplified version of what I’m doing:

import simpy
import random

class Machine:
    def __init__(self, env, processing_time):
        self.env = env
        self.processing_time = processing_time
        self.process = env.process(self.run())

    def run(self):
        while True:
            yield self.env.timeout(self.processing_time)
            print(f"Processed at {self.env.now}")

def build_model(env, processing_time):
    return Machine(env, processing_time)

# Run simulations with different parameters
for processing_time in [5, 10, 15]:
    env = simpy.Environment()
    machine = build_model(env, processing_time)  # Instead of rebuilding I'd like to recycle the once build model with a new environment to start a new simulation at env.now = 0
    env.run(until=50)

This works, but in the real model, build_model() initializes many interconnected components, which makes frequent rebuilding expensive.

What I’d like to do instead:

  • Reuse the structure (e.g., machine instances)

  • Just reset the env or "rebind" the model components to a new environment

  • Avoid reinitializing the full model tree

Is there a way to decouple the environment more cleanly or restructure my model for this kind of reuse? Any design patterns or best practices for this kind of use case?

Thanks in advance for any tips or ideas!

Adrian Mc

unread,
May 22, 2025, 9:45:26 AMMay 22
to python-simpy
Hi, 

Why don’t you run multiple simulations concurrently with different parameters?

Regards,
Adrian. 

Cornelius Sheahan

unread,
May 22, 2025, 10:55:09 AMMay 22
to Adrian Mc, python-simpy
Hi,

Couldn't you just make an initialization method that does all the setup/ resetup for each simulation and call that at the start of each experiment?

Regards,
Neil

--
You received this message because you are subscribed to the Google Groups "python-simpy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python-simpy...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/python-simpy/19b8463d-c363-4c3c-abf7-d030dc7c4a05n%40googlegroups.com.

henrikw

unread,
Jun 20, 2025, 6:19:33 AMJun 20
to python-simpy
Hi,

thank you for your input.
I solved the issue by overwriting each env-dependent attribute of my simulation objects with a new env. However when overwriting environments, it seems to be important to keep track of the memory allocations because old environments and potentially additional objects will be kept inside memory and therefore slowing down the simulation while overloading memory.

Regards,
Henrik

rac...@clarke.gen.nz

unread,
Oct 5, 2025, 7:27:35 PM (2 days ago) Oct 5
to python-simpy
Hi Henrik,

I'm planning on taking the same approach as I have some resources in my model that process items, but the configuration of them doesn't change from iteration to iteration. 

Are you able to provide any further details on how you managed the memory allocation issue?  I have noticed it getting quite large without a huge number of iterations.

Thank you
Rachel

henrikw

unread,
Oct 6, 2025, 3:26:06 AM (21 hours ago) Oct 6
to python-simpy
Hi Rachel,

to reset SimPy-based models with multiple components (e.g., processing machines), I orchestrate all components within a meta class called Model.
To make the model reusable and avoid rebuilding it from scratch in each iteration, every component is extended by a reset() method, which optionally accepts a new SimPy Environment as a parameter.
When the model is “reset”, all SimPy-related attributes of its components are reinitialized using the new environment:

import simpy
import gc
import objgraph

class Machine:
def __init__(self, env, processing_time, capacity=1):

self.env = env
self.processing_time = processing_time
self.capacity = capacity
self.resource = simpy.Resource(env, capacity=self.capacity)
self.action = env.process(self.run())
self.is_processing = env.event()


def run(self):
while True:
yield self.env.timeout(self.processing_time)
print(f"Processed at {self.env.now}")

def reset(self, env: simpy.Environment = None):
# Reset attributes unrelated to SimPy.
# ...

# Reinitialize the SimPy-related parts of the object.
if env:
# Replace the old environment reference.
self.env = env
# Recreate environment-dependent attributes.
self.resource = simpy.Resource(env, capacity=self.capacity)
self.action = env.process(self.run())
self.is_processing = env.event()

class Model:
def __init__(self, env, processing_time):
self.machine = Machine(env, processing_time)

def reset(self, env):
# Reset all components with the new environment.
self.machine.reset(env)

# Example usage:
def run_simulation(iterations=5):
model = None
for i in range(iterations):
env = simpy.Environment()
if model is None:
# Build model only once.
model = Model(env, processing_time=5)
else:
# Just reset environment references.
model.reset(env)
# Evaluate the model or ave its simulation results.

# Check the results of the reset.
#gc.collect()
print("Simpy envs in memory:", sum(1 for o in gc.get_objects() if isinstance(o, simpy.Environment)))
objgraph.show_growth()

env.run(until=20)
print(f"Iteration {i+1} done\n")

run_simulation()


While this example is simplified, it demonstrates the reset procedure I use in my implementation.
The model itself is built only once, and then reset for every subsequent iteration using a new SimPy environment.

To ensure that only one SimPy environment remains in memory, I manually call the garbage collector (gc.collect()).

If you skip this step, the first SimPy environment will still be referenced somewhere and stay in memory — meaning you’ll typically see two environments at all times. However, since this number doesn’t increase over iterations, it’s usually not a problem.

To further verify that memory usage stays stable, I print out the number of SimPy environments currently in memory, and also display the number of newly created objects using objgraph.show_growth() after each reset.

This approach prevents my model from accumulating memory over time while allowing me to efficiently reset the SimPy environment between iterations.

Hope this helps!
Feel free to reach out if you have any more questions.

Henrik

jar...@gmail.com

unread,
Oct 6, 2025, 3:23:10 PM (9 hours ago) Oct 6
to python-simpy
This is fascinating. I have not been able to have `gc.collect` clear an environment object before. I haven't tried doing an in-place modification, either. I've been forced to restart python environments to deal with memory explosions before, even when having an entire sim run inside a function, only returning data, and gc.collecting after the fact.

I even went so far as to put the environment in a context manager to be deleted on exit. Still no luck with whatever mutually dependent objects held references to each other I guess.

James
Reply all
Reply to author
Forward
0 new messages