Skip to content

Fix unbounded growth of Model._event_generators#3317

Merged
EwoutH merged 1 commit intomesa:mainfrom
EwoutH:eventgenerator_set
Feb 15, 2026
Merged

Fix unbounded growth of Model._event_generators#3317
EwoutH merged 1 commit intomesa:mainfrom
EwoutH:eventgenerator_set

Conversation

@EwoutH
Copy link
Copy Markdown
Member

@EwoutH EwoutH commented Feb 15, 2026

Summary

Model._event_generators grows unbounded because exhausted and stopped EventGenerators are never removed.

Bug / Issue

_event_generators exists solely to hold strong references to active generators, preventing garbage collection. However, generators were never removed when they finished or were stopped, causing the list to grow indefinitely. Since generators hold hard references to their callables (which may be bound agent methods), this could also prevent agents from being garbage collected.

Closes #3313.

Implementation

  • Changed _event_generators from list to set (ordering is irrelevant for a GC-prevention container).
  • Moved registration responsibility into EventGenerator: start() adds itself to the set, stop() and exhaustion remove it via discard().
  • Removed the _event_generators.append() call from Model.schedule_recurring, since start() now handles it.

Testing

Existing tests pass. Could add a test verifying that a generator with count=n is removed from _event_generators after completing its executions.

Additional Notes

No public API changes, _event_generators is a private attribute.

Change Model._event_generators from a list to a set and move registration responsibility into EventGenerator. EventGenerator now adds itself to model._event_generators when scheduled and discards itself on stop/cancel; the model no longer appends generators. This avoids duplicate entries, enables O(1) add/remove, and keeps strong references to active generators to prevent GC.
@EwoutH EwoutH requested a review from quaquel February 15, 2026 19:36
@EwoutH EwoutH added the bug Release notes label label Feb 15, 2026
@EwoutH
Copy link
Copy Markdown
Member Author

EwoutH commented Feb 15, 2026

When designing this part I thought this would be a problem, because now an EventGenerator can't be restarted anymore. But that's not true, because:

  • If you create a reference you can use that to restart it
  • If you didn't create a reference yourself you couldn't apply start to it anyways

So this nicely solves itself.

@EwoutH EwoutH added backport backport-candidate PRs we might want to backport to an earlier branch and removed backport labels Feb 15, 2026
@quaquel
Copy link
Copy Markdown
Member

quaquel commented Feb 15, 2026

If you create a reference you can use that to restart it

What do you mean by restarting?

@EwoutH
Copy link
Copy Markdown
Member Author

EwoutH commented Feb 15, 2026

Calling .start() after you have called .stop()

@EwoutH EwoutH merged commit 1365047 into mesa:main Feb 15, 2026
17 of 18 checks passed
@quaquel
Copy link
Copy Markdown
Member

quaquel commented Feb 15, 2026

Fair enough.

Krishsharma179 pushed a commit to Krishsharma179/mesa that referenced this pull request Feb 21, 2026
Change Model._event_generators from a list to a set and move registration responsibility into EventGenerator. EventGenerator now adds itself to model._event_generators when scheduled and discards itself on stop/cancel; the model no longer appends generators. This avoids duplicate entries, enables O(1) add/remove, and keeps strong references to active generators to prevent GC.
@EwoutH EwoutH added backport and removed backport-candidate PRs we might want to backport to an earlier branch labels Mar 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport bug Release notes label

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Model._event_generators grows unbounded

2 participants