Performance bottlenecks in mesa.discrete_space
- Dominant language
- Python
- Stars
- 3.9k
- Forks
- 1.3k
- Avg merge
- 2d 12h
- Merged PRs (30d)
- 20
Description
**Summary**
While profiling mesa.discrete_space under a high-movement workload, I observed significant time spent in cell movement and occupancy checks. This issue summarizes the hotspots and proposes a few improvements.
**Reproduction**
````python
import random
import cProfile
from mesa import Model
from mesa.discrete_space.grid import OrthogonalVonNeumannGrid
from mesa.discrete_space.cell_agent import CellAgent
class DummyModel(Model):
pass
def run_benchmark():
model = DummyModel()
grid = OrthogonalVonNeumannGrid((100, 100), capacity=1)
agents = [CellAgent(model) for _ in range(5000)]
# initial placement
for agent in agents:
agent.cell = grid.select_random_empty_cell()
# random movement loop
for _ in range(500):
for agent in agents:
neighbors = agent.cell.neighborhood
target = random.choice(list(neighbors))
if target.is_empty:
agent.cell = target
if __name__ == "__main__":
cProfile.run("run_benchmark()", sort="cumtime")
````
**Observations**
- `Cell.is_empty` is called very frequently and currently computes `len(self._agents) == 0` every time.
- `CellAgent.cell` triggers add or remove operations that account for a large portion of total runtime.
- Neighborhood access wraps results in `CellCollection` and constructs intermediate mappings, contributing additional allocation overhead.
Total runtime is around 63 seconds
````
CellAgent.cell ~14.7s
Cell.is_empty ~11.1s
Cell.neighborhood ~6.8s
Cell.remove_agent ~6.1s
Cell.add_agent ~4.8s
````
**Proposed Improvements**
- Make `_empty` the single source of truth for emptiness and avoid recomputing `len(self._agents)` on every `is_empty` call.
- Reduce overhead in the movement pathnto avoid unnecessary repeated checks and work.
- Simplify how neighborhoods are constructed and returned to reduce intermediate allocations during frequent movement.
I plan to address these in separate PRs to keep changes focused and measurable.
Contributor guide
Research direction
Start by running the provided cProfile benchmark, then inspect Cell.is_empty, CellAgent.cell, Cell.add_agent, Cell.remove_agent, and neighborhood access in mesa.discrete_space. Treat the proposed changes as separate, measurable efforts; done means reducing the identified hotspots without changing movement or occupancy behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- performance
- Issue type
- Refactor
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100