Mapping Salabim to SimPy: Comparing the Two Python Discrete-Event Simulation Powerhouses
Also In the Series
Siemens Plant Simulation vs SimPy
Introduction
If you're experienced in simulation, particularly in Python, you're probably familiar with the range of libraries available to implement discrete-event simulation (DES) effectively. Two prominent contenders in this space are salabim and SimPy - each offering distinct features, philosophies, and strengths.
In this article, I'm going to take a close look at each of these library’s key features and how their fundamental building blocks can be mapped to each other. So if you're currently using one library and considering making the leap to the other, or just curious how the two libraries stack up, you'll find the parallels clearly illustrated.
Both libraries share the same broad goal - simplifying discrete-event simulation; but they differ significantly in approach, usability, and underlying philosophy. By the end, salabim users should recognise how to accomplish familiar tasks in SimPy’s syntax, and SimPy users will understand how SimPy’s simplicity contrasts with salabim’s more feature-rich API.
Introduction
DES is a powerful technique for modeling complex processes in many critical industries. It allows one experiment with scenarios in-silico to optimise operations and improve decision-making without disrupting real-world systems. In the Python ecosystem, two widely used DES libraries are SimPy and salabim. Both leverage Python’s simplicity and extensive scientific ecosystem to enable efficient modeling of processes, but they originate from different backgrounds and design philosophies.
SimPy is a process-based DES framework for Python that first emerged in the early 2000s. It was originally developed by Klaus Müller and Tony Vignaux, inspired by earlier simulation languages Simula and SIMSCRIPT. Over the years, SimPy has been maintained as an open-source project (now under the MIT license) with a robust community contributing to its development and support. SimPy introduced a clean, generator-based approach to simulation, which many appreciate for its Pythonic elegance.
Salabim is a more recent entrant, created around 2016 by Ruud van der Ham. Ruud, a veteran in simulation since the 1970s, developed salabim to address some limitations he perceived in SimPy’s then-current design. In particular, SimPy version 3 had removed certain classic process interaction methods (like activate, hold, passivate, standby) which were present in SimPy 2 and other simulation Simula like languages. Salabim was born to reintroduce these concepts and to provide an “all-in-one” simulation toolkit including not just process logic but also built-in animation and monitoring capabilities. The name salabim itself is inspired by the magic words “Sim Sala Bim,” hinting at its focus on simulation (“Sim”) made easy. Salabim’s core developer remains Ruud van der Ham, and the library has steadily grown with features and bug fixes, now available on PyPI and GitHub for easy installation and collaboration.
Python’s popularity in scientific computing is a key reason both SimPy and salabim are used in DES. Python offers clear syntax and a rich ecosystem of libraries (for data analysis, machine learning, visualisation, etc.), which means simulation models can be easily extended with analytics or integrated into larger applications.
Key Features and Design Philosophies
Both SimPy and Salabim are process-oriented DES libraries, meaning they model system entities as “processes” that evolve over time and interact with each other and with shared resources. However, the way each library implements this has notable differences:
SimPy’s Approach
SimPy uses Python generator functions to define processes. Each process is typically a function (or method) that yields events (such as timeouts or resource requests). When a process yields an event, it is paused, allowing other events to be processed; once the yielded event is completed, the process resumes where it left off. For example, a SimPy process might yield env.timeout(5) to wait 5 time units. The SimPy Environment orchestrates all these events in a time-ordered sequence.
This design, rooted in coroutines, leads to very clear and linear code for each process, even though multiple processes run concurrently. SimPy provides a set of core components: an Environment, Timeout events for delays, and Resource types (like Resource, Container, Store) to model limited-capacity resources and queues.
Notably, SimPy does not include built-in visualisation or GUI elements – it focuses purely on the simulation logic, leaving any output or visualisation to the user or external tools. This lean design reflects a philosophy of being a lightweight toolkit that can be extended or integrated as needed.
The emphasis is on clarity and Pythonic syntax: for instance, SimPy uses the with resource.request() context manager to automatically handle resource acquisition and release, which many find intuitive.
Salabim’s Approach
Salabim is object-oriented and was influenced by the process description style of Simula and later languages like Prosim, Must, and Tomas. In salabim, one typically defines a subclass of sim.Component for each active entity in the system. The behavior of that entity is described in a process(self) generator method of the class, similar to SimPy’s generator functions but tied to an object instance. For example, a Truck or Patient might be a subclass of sim.Component with a process method that calls yield self.hold(5) to wait 5 time units.
Under the hood, salabim’s process interaction methods like hold (for delays), request/release (for resources), passivate/activate (to deactivate/reactivate a process), etc., are very much in line with classic DES terminology (in fact, they resemble SimPy 2’s API). Apart from resources, salabim supports states, which allow a component to wait for a certain condition. One of salabim’s unique offerings is its animation engine: it can produce real-time 2D (and even rudimentary 3D) animations of the simulation, showing entities moving, queues forming, resources being utilised, etc., without the user needing to integrate a separate visualisation library. The animation engine can also be used to interact with the simulation by pausing, setting variables, changing the speed, etc. This can be extremely useful for debugging.
This makes salabim attractive for simulations where visual insight or stakeholder demonstration is important (e.g., showing a conveyor belt system in a factory, or patient movement through hospital units). Salabim also includes built-in monitoring and statistics collection objects, which can simplify gathering simulation results, without having to rely on other libraries.
Despite these differences, both libraries rely on Python’s interpreter to manage simulation time progression. Neither uses any specialised simulation language syntax – they are pure Python libraries, which is a major advantage for users already comfortable with Python.
Extensibility and Usability Philosophy
SimPy’s minimalist core means it’s easy to fit into other Python workflows. For example, one can run a SimPy model and then use pandas or NumPy to analyse the results, or integrate the simulation within a larger application (since SimPy doesn’t enforce any GUI or particular structure beyond the environment). Its philosophy is “bring your own” tools for anything beyond the core simulation logic.
On the other hand, salabim strives to be a one-stop simulation environment: the trade-off is a larger feature set to learn, but many common needs (animation, queuing objects, result monitors) are readily available.
Salabim’s design also offers a “yieldless” mode: by leveraging the greenlet library, Salabim can allow writing processes without explicit yield statements. In yieldless mode, a salabim process method might simply call self.hold(3) without yielding, and the library takes care of scheduling. This can make the code look more sequential (closer to how one might write in a simulation language like Simula or Arena) and can be easier for newcomers to follow. By default, Salabim enables yieldless mode for convenience, but users can disable it to use the traditional generator-yield approach. SimPy, by contrast, relies always on Python’s built-in generators.
In summary, SimPy’s philosophy is simplicity and integration – it focuses on core simulation primitives with clean syntax and relies on Pythonic patterns. Salabim’s philosophy is feature-rich simulation – it provides a fuller toolkit for simulation projects (including visual and interactive elements) and sticks to classic simulation concepts, aiming to make complex models straightforward to build. These philosophies influence the user experience, as we’ll explore through a direct comparison of features.
Key Features, Strengths, and Weaknesses
The following table provides a side-by-side comparison of SimPy and salabim on several aspects that matter to practitioners:
In essence, SimPy shines for its elegant minimalism and proven track record, whereas salabim offers a more batteries-included approach tailored for simulation practitioners who want more than just a raw simulation engine. The next sections will dive deeper into how each library implements core simulation concepts and provide code examples in industrial contexts.
Mapping Simulation Building Blocks
To better understand the differences and similarities, let’s map how core DES concepts are handled in SimPy vs. Salabim. Both libraries need to provide ways to advance time, manage queues and resources, and define processes. Here’s a look at these building blocks side by side:
In practical terms, a user of SimPy and Salabim will find that basic modeling tasks (waiting for time, seising resources, releasing resources, collecting data) can be done in both, but the syntax and constructs differ. SimPy might require a bit more boilerplate for things like releasing a resource (unless using the with statement) or setting up an event for communication, whereas salabim might provide a method on the component to achieve the same (e.g., component.wait(event)). Salabim’s additional structures (Queue, Store, State, Monitor, etc.) mirror many concepts one would build manually in SimPy.
Example Usage
To illustrate the usage of SimPy and salabim, we will consider two simple scenarios: a mining operation where trucks queue for a loading station, and a hospital where patients wait for service. These examples focus on clarity, not optimising for performance, and demonstrate how each library expresses the simulation logic.
Mining Process Example (Truck Loading Station)
In a mining operation, trucks arrive at a loading station to be filled with ore. The station has a single loader (resource) that can serve one truck at a time, so other trucks must wait in a queue until the loader is free. We’ll model a few trucks arriving at fixed intervals and requiring a certain loading time.
Using SimPy:
In the SimPy code above, each truck is represented by the generator function truck. We create three such processes with different arrival times. Each truck yields env.timeout() to simulate travel time before arriving, then requests the loader. If the loader is busy, the process will pause at the yield req line and automatically queue until the resource is free.
The environment run loop advances time and manages the queue behind the scenes.
Using Salabim:
In the salabim code, we define a Truck class inheriting from sim.Component. Instead of an explicit arrival delay inside process(), we schedule the creation of the Truck at a specific simulation time. When a Truck is created at its scheduled time, its process method starts immediately, and the first action is to request the loader. If the loader is busy, salabim automatically puts the Truck in the loader’s queue (loader.requesters() is the queue of waiting components). Once the loader is acquired, the truck holds it for the loading duration, then the process ends and the loader is free for the next request. Note that Salabim also allows a design where the Truck process itself handles arrival via self.hold(arrival_delay) at the start, which would be more analogous to the SimPy version – here we demonstrated an alternative by scheduling components at specific times.
Both implementations achieve the same logical result: trucks wait their turn for the loader. In SimPy, the flow is controlled by yields in a single function, whereas in salabim the logic is split between when the component is scheduled/created and its internal process. Salabim can automatically trace all events on the console, which helps debugging.
Hospital Patient Flow Example
For a healthcare scenario, consider a small clinic where patients arrive periodically, consult with a doctor (assuming one doctor available), and then leave. If the doctor is busy, arriving patients will wait.
Using SimPy:
This SimPy snippet creates five patient processes spaced 3 time units apart (0, 3, 6, 9, 12). Each patient waits if necessary for the doctor resource and then yields a timeout for their service. The print statements (for illustration) would show the queue behavior, e.g., second patient arriving at time 3 might have to wait until time 5 if the first patient’s 5-unit service isn’t finished.
Using salabim:
In salabim’s version, we create a Patient component for each arrival. We directly schedule each Patient at the given arrival time. The patient’s process immediately requests the doctor; if the doctor is busy, salabim queues the Patient. Once the patient gets the doctor, they hold it for service_time units. After that, the patient’s process ends, releasing the doctor. This code achieves the same behavior as the SimPy model. We used the salabim pattern of scheduling components at future times to handle arrivals (alternatively, we could have used the very useful generic ComponentGeneratort to create and activate patients.
Focus on clarity: In both examples, we prioritised clear, step-by-step logic: each process first waits for its arrival, then requests a resource, then simulates the service. Both libraries allow printing or logging (as shown in SimPy) to trace the simulation; Salabim also can automatically trace events if enabled (e.g., by env = sim.Environment(trace=True)). The code differences highlight how SimPy uses the environment and procedural code, while salabim uses object-oriented components and scheduling. Depending on your background, one style may seem more intuitive than the other.
Documentation
The SimPy documentation provides an overview of its design and examples, and the salabim documentation and user manual detail its components and philosophy. Interested readers should consult the official docs for deeper technical details, advanced features, and the latest updates (SimPy’s docs on ReadTheDocs and salabim’s manual on salabim.org). Salabim documentation is also available in pdf format and as a printed book.
Both projects are open-source, so their source code and issue trackers (on GitLab for SimPy and GitHub for salabim) are also great resources to understand their development and to seek support or contribute. Both SimPy and salabim have a Google user group.
Final Words
SimPy and salabim are both powerful tools for discrete-event simulation in Python, each with its own niche. SimPy offers a clean, minimalist framework that integrates easily into the broader Python data science stack – it’s often the go-to choice for quick models, teaching simulation concepts, or embedding a simulation in a larger application where custom analysis or visualisation will be applied externally. Salabim, on the other hand, provides a richer standalone simulation environment, ideal for projects that benefit from built-in animation or where the model complexity aligns with classic DES patterns (making use of salabim’s passivate, hold, etc., can simplify some scenarios).
When choosing between them, consider the project scope and requirements: If you need to quickly prototype a model or have team members new to simulation, SimPy’s gentle learning curve and abundance of examples might be advantageous. If your project involves showcasing the simulation to stakeholders (e.g., a live demo of a particular system), Salabim’s animation features and monitoring can save a lot of development time and convey results more intuitively. Also factor in the team’s preferences: some may prefer the procedural style of SimPy, while others coming from an Arena/Simul8 background might find salabim’s component paradigm more familiar.
Importantly, both libraries are actively maintained and not mutually exclusive. They are lightweight enough that you could experiment with both on a small prototype of your problem before committing. Because they are Python-based, you’ll find that whichever you choose, you can harness Python’s capabilities (for input data handling, output analysis, integration with optimisation or machine learning frameworks, etc.) just as well.
Both salabim and SimPy enable discrete-event simulation in Python, but they do so with distinct philosophies.
Ultimately, both libraries share the goal of making DES in Python effective and accessible, which is a noble mission. They simply take different routes to get there.
Resources
If you’re ready to explore SimPy further and want a deeper dive into best practices, examples, and tips for success, we’ve got something for you. Download my free guide to simulation in Python with SimPy for a comprehensive walkthrough of building DES models in Python - from basic queuing systems to complex supply chain networks. It’s packed with code samples and conversion tips for SimEvents users. Download the Free Guide Here and take your simulation skills to the next level in an open-source world!
SimPy official documentation: https://simpy.readthedocs.io/en/latest/
Salabim website: https://www.salabim.org/
Senior Backend Developer | Python and Java Software Engineer
1wThank you, Harry!
Sustainability || Industry 4.0 || Manufacturing Systems
5moInteresting
Thanks!