SimPy PriorityResource Explained: When Some Requests Matter More
Not all customers are equal. Not all jobs are equally urgent. PriorityResource lets important requests jump the queue.
Basic Resource vs PriorityResource
Regular Resource: First come, first served. Fair. Simple.
PriorityResource: Lower priority number goes first. VIPs jump the queue.
import simpy
env = simpy.Environment()
resource = simpy.PriorityResource(env, capacity=1)
How Priority Works
Lower numbers = higher priority.
def requester(env, name, resource, priority):
with resource.request(priority=priority) as req:
yield req
print(f"{name} (priority {priority}) gets resource at {env.now}")
yield env.timeout(5)
env = simpy.Environment()
resource = simpy.PriorityResource(env, capacity=1)
# First request (lowest priority)
env.process(requester(env, "Low", resource, priority=10))
# Second request (highest priority)
env.process(requester(env, "High", resource, priority=1))
# Third request (medium priority)
env.process(requester(env, "Medium", resource, priority=5))
env.run()
Output:
Low (priority 10) gets resource at 0
High (priority 1) gets resource at 5
Medium (priority 5) gets resource at 10
"Low" was first, so it got the resource. But when it released, "High" jumped ahead of "Medium" in the queue.
Real-World Examples
Emergency Department Triage
PRIORITY = {
'critical': 1,
'urgent': 2,
'standard': 3,
'minor': 4
}
def patient(env, name, doctor, severity):
print(f"{name} ({severity}) arrives at {env.now}")
with doctor.request(priority=PRIORITY[severity]) as req:
yield req
print(f"{name} sees doctor at {env.now}")
yield env.timeout(10)
env = simpy.Environment()
doctor = simpy.PriorityResource(env, capacity=1)
env.process(patient(env, "Alice", doctor, "minor"))
env.process(patient(env, "Bob", doctor, "critical"))
env.process(patient(env, "Charlie", doctor, "urgent"))
env.run()
Bob (critical) jumps ahead of Charlie (urgent), who jumps ahead of Alice (minor).
Job Scheduling
def job(env, name, machine, priority, duration):
with machine.request(priority=priority) as req:
yield req
print(f"{name} starts at {env.now}")
yield env.timeout(duration)
machine = simpy.PriorityResource(env, capacity=1)
# Customer jobs (low priority)
env.process(job(env, "Routine", machine, priority=10, duration=5))
# Expedited order (high priority)
env.process(job(env, "Rush", machine, priority=1, duration=5))
Ties: Same Priority
When priorities are equal, FIFO applies:
env.process(requester(env, "A", resource, priority=5))
env.process(requester(env, "B", resource, priority=5))
env.process(requester(env, "C", resource, priority=5))
A, B, C get served in order—no favouritism among equals.
Dynamic Priority
Priority is set at request time, not at process creation:
def smart_customer(env, resource):
wait_start = env.now
# Start with normal priority
priority = 5
# But if I've been waiting too long, escalate
if env.now - wait_start > 10:
priority = 1
with resource.request(priority=priority) as req:
yield req
# ...
You could also implement aging—increasing priority the longer someone waits.
Priority vs Regular Resource
| Feature | Resource | PriorityResource |
|---|---|---|
| Queue order | FIFO | Priority, then FIFO |
| Request syntax | request() |
request(priority=n) |
| Fair | Yes | No (by design) |
When to Use PriorityResource
Use when: - Some entities genuinely deserve faster service - SLAs require tiered response times - Business value varies by customer/job type - You're modelling emergency services or triage
Don't use when: - Fairness matters - Priority abuse is a concern (low priority starves) - The real system doesn't prioritise
Starvation Warning
Priority queues can starve low-priority requests:
def high_priority_flood(env, resource):
"""Continuous stream of high-priority requests"""
while True:
yield env.timeout(1)
env.process(quick_job(env, resource, priority=1))
If high-priority requests keep arriving, low-priority requests wait forever.
Solutions: - Age-based priority boosting - Reserved capacity for low priority - Maximum wait time enforcement
Collecting Statistics by Priority
wait_times = {1: [], 2: [], 3: []}
def job(env, resource, priority):
arrival = env.now
with resource.request(priority=priority) as req:
yield req
wait_times[priority].append(env.now - arrival)
yield env.timeout(5)
# After simulation
for p, times in wait_times.items():
avg = sum(times) / len(times) if times else 0
print(f"Priority {p} average wait: {avg:.2f}")
PriorityResource vs PreemptiveResource
PriorityResource: High priority jumps the queue but waits for current user to finish.
PreemptiveResource: High priority can interrupt and take over immediately.
The difference is not insignificant. PriorityResource respects current users. PreemptiveResource doesn't.
Example: Call Centre with VIP Line
import random
def caller(env, name, agents, is_vip):
priority = 1 if is_vip else 5
arrival = env.now
print(f"{name} ({'VIP' if is_vip else 'Regular'}) calls at {env.now}")
with agents.request(priority=priority) as req:
yield req
wait = env.now - arrival
print(f"{name} answered after {wait:.1f} (priority {priority})")
yield env.timeout(random.uniform(3, 8))
env = simpy.Environment()
agents = simpy.PriorityResource(env, capacity=2)
for i in range(10):
is_vip = random.random() < 0.2 # 20% VIP
env.process(caller(env, f"Caller{i}", agents, is_vip))
yield env.timeout(random.expovariate(1))
env.run()
Summary
PriorityResource: - Serves lower priority numbers first - FIFO among equal priorities - Doesn't interrupt current service - Use for triage, tiered SLAs, job scheduling
When priority matters, use PriorityResource.
Next Steps
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