Files
2025-11-30 08:30:10 +08:00

7.2 KiB

SimPy Shared Resources

This guide covers all resource types in SimPy for modeling congestion points and resource allocation.

Resource Types Overview

SimPy provides three main categories of shared resources:

  1. Resources - Limited capacity resources (e.g., gas pumps, servers)
  2. Containers - Homogeneous bulk materials (e.g., fuel tanks, silos)
  3. Stores - Python object storage (e.g., item queues, warehouses)

1. Resources

Model resources that can be used by a limited number of processes at a time.

Resource (Basic)

The basic resource is a semaphore with specified capacity.

import simpy

env = simpy.Environment()
resource = simpy.Resource(env, capacity=2)

def process(env, resource, name):
    with resource.request() as req:
        yield req
        print(f'{name} has the resource at {env.now}')
        yield env.timeout(5)
        print(f'{name} releases the resource at {env.now}')

env.process(process(env, resource, 'Process 1'))
env.process(process(env, resource, 'Process 2'))
env.process(process(env, resource, 'Process 3'))
env.run()

Key properties:

  • capacity - Maximum number of concurrent users (default: 1)
  • count - Current number of users
  • queue - List of queued requests

PriorityResource

Extends basic resource with priority levels (lower numbers = higher priority).

import simpy

env = simpy.Environment()
resource = simpy.PriorityResource(env, capacity=1)

def process(env, resource, name, priority):
    with resource.request(priority=priority) as req:
        yield req
        print(f'{name} (priority {priority}) has the resource at {env.now}')
        yield env.timeout(5)

env.process(process(env, resource, 'Low priority', priority=10))
env.process(process(env, resource, 'High priority', priority=1))
env.run()

Use cases:

  • Emergency services (ambulances before regular vehicles)
  • VIP customer queues
  • Job scheduling with priorities

PreemptiveResource

Allows high-priority requests to interrupt lower-priority users.

import simpy

env = simpy.Environment()
resource = simpy.PreemptiveResource(env, capacity=1)

def process(env, resource, name, priority):
    with resource.request(priority=priority) as req:
        try:
            yield req
            print(f'{name} acquired resource at {env.now}')
            yield env.timeout(10)
            print(f'{name} finished at {env.now}')
        except simpy.Interrupt:
            print(f'{name} was preempted at {env.now}')

env.process(process(env, resource, 'Low priority', priority=10))
env.process(process(env, resource, 'High priority', priority=1))
env.run()

Use cases:

  • Operating system CPU scheduling
  • Emergency room triage
  • Network packet prioritization

2. Containers

Model production and consumption of homogeneous bulk materials (continuous or discrete).

import simpy

env = simpy.Environment()
container = simpy.Container(env, capacity=100, init=50)

def producer(env, container):
    while True:
        yield env.timeout(5)
        yield container.put(20)
        print(f'Produced 20. Level: {container.level}')

def consumer(env, container):
    while True:
        yield env.timeout(7)
        yield container.get(15)
        print(f'Consumed 15. Level: {container.level}')

env.process(producer(env, container))
env.process(consumer(env, container))
env.run(until=50)

Key properties:

  • capacity - Maximum amount (default: float('inf'))
  • level - Current amount
  • init - Initial amount (default: 0)

Operations:

  • put(amount) - Add to container (blocks if full)
  • get(amount) - Remove from container (blocks if insufficient)

Use cases:

  • Gas station fuel tanks
  • Buffer storage in manufacturing
  • Water reservoirs
  • Battery charge levels

3. Stores

Model production and consumption of Python objects.

Store (Basic)

Generic FIFO object storage.

import simpy

env = simpy.Environment()
store = simpy.Store(env, capacity=2)

def producer(env, store):
    for i in range(5):
        yield env.timeout(2)
        item = f'Item {i}'
        yield store.put(item)
        print(f'Produced {item} at {env.now}')

def consumer(env, store):
    while True:
        yield env.timeout(3)
        item = yield store.get()
        print(f'Consumed {item} at {env.now}')

env.process(producer(env, store))
env.process(consumer(env, store))
env.run()

Key properties:

  • capacity - Maximum number of items (default: float('inf'))
  • items - List of stored items

Operations:

  • put(item) - Add item to store (blocks if full)
  • get() - Remove and return item (blocks if empty)

FilterStore

Allows retrieval of specific objects based on filter functions.

import simpy

env = simpy.Environment()
store = simpy.FilterStore(env, capacity=10)

def producer(env, store):
    for color in ['red', 'blue', 'green', 'red', 'blue']:
        yield env.timeout(1)
        yield store.put({'color': color, 'time': env.now})
        print(f'Produced {color} item at {env.now}')

def consumer(env, store, color):
    while True:
        yield env.timeout(2)
        item = yield store.get(lambda x: x['color'] == color)
        print(f'{color} consumer got item from {item["time"]} at {env.now}')

env.process(producer(env, store))
env.process(consumer(env, store, 'red'))
env.process(consumer(env, store, 'blue'))
env.run(until=15)

Use cases:

  • Warehouse item picking (specific SKUs)
  • Job queues with skill matching
  • Packet routing by destination

PriorityStore

Items retrieved in priority order (lowest first).

import simpy

class PriorityItem:
    def __init__(self, priority, data):
        self.priority = priority
        self.data = data

    def __lt__(self, other):
        return self.priority < other.priority

env = simpy.Environment()
store = simpy.PriorityStore(env, capacity=10)

def producer(env, store):
    items = [(10, 'Low'), (1, 'High'), (5, 'Medium')]
    for priority, name in items:
        yield env.timeout(1)
        yield store.put(PriorityItem(priority, name))
        print(f'Produced {name} priority item')

def consumer(env, store):
    while True:
        yield env.timeout(5)
        item = yield store.get()
        print(f'Retrieved {item.data} priority item')

env.process(producer(env, store))
env.process(consumer(env, store))
env.run()

Use cases:

  • Task scheduling
  • Print job queues
  • Message prioritization

Choosing the Right Resource Type

Scenario Resource Type
Limited servers/machines Resource
Priority-based queuing PriorityResource
Preemptive scheduling PreemptiveResource
Fuel, water, bulk materials Container
Generic item queue (FIFO) Store
Selective item retrieval FilterStore
Priority-ordered items PriorityStore

Best Practices

  1. Capacity planning: Set realistic capacities based on system constraints
  2. Request patterns: Use context managers (with resource.request()) for automatic cleanup
  3. Error handling: Wrap preemptive resources in try-except for Interrupt handling
  4. Monitoring: Track queue lengths and utilization (see monitoring.md)
  5. Performance: FilterStore and PriorityStore have O(n) retrieval time; use wisely for large stores