Skip to content

Replace Computable Descriptor with @computed in mesa_signals#3153

Merged
quaquel merged 5 commits intomesa:mainfrom
codebreaker32:signal/computable-computed
Jan 17, 2026
Merged

Replace Computable Descriptor with @computed in mesa_signals#3153
quaquel merged 5 commits intomesa:mainfrom
codebreaker32:signal/computable-computed

Conversation

@codebreaker32
Copy link
Copy Markdown
Collaborator

@codebreaker32 codebreaker32 commented Jan 16, 2026

This PR modifies mesa_signals to move from a class-based descriptor pattern (Computable/Computed) to a standard Python property factory (@computed).

Currently, accessing a derived property triggers the Computable.__get__ descriptor, which then fetches a separate Computed object to execute the logic. This adds unnecessary function call depth to every attribute access.

I suggest two streamlined components:

  1. @computed Decorator: A factory that returns a standard Python property. The "reactive" logic (dependency tracking, dirty checking) is captured in the property's closure, eliminating the descriptor lookup overhead.
  2. ComputedState: A lightweight, internal-only class using __slots__ to hold the value, dirty flag, and dependencies.
  • ComputedProperty: A custom property class to identify computed properties.

API Changes (Before vs. After)

Before (Current)

class MyAgent(HasObservables):
    wealth = Computable()  # Descriptor

    def __init__(self):
        super().__init__()
        # Manual binding required
        self.wealth = Computed(self._calculate_wealth)

    def _calculate_wealth(self):
        return self.cash + self.assets

After

class MyAgent(HasObservables):
    @computed
    def wealth(self):  # Clean, standard Python syntax
        return self.cash + self.assets

Addresses (2) from #3131

@codebreaker32 codebreaker32 changed the title Replace Computable Descriptor with @computed Replace Computable Descriptor with @computed in mesa_signals Jan 16, 2026
@github-actions
Copy link
Copy Markdown

Performance benchmarks:

Model Size Init time [95% CI] Run time [95% CI]
BoltzmannWealth small 🔴 +4.0% [+3.2%, +4.8%] 🔵 -0.7% [-0.9%, -0.6%]
BoltzmannWealth large 🔵 +2.3% [+1.0%, +3.3%] 🔴 +14.1% [+12.1%, +16.3%]
Schelling small 🔴 +4.3% [+3.9%, +4.6%] 🔴 +3.5% [+3.1%, +4.0%]
Schelling large 🔵 +1.0% [+0.8%, +1.2%] 🔴 +19.5% [+17.3%, +21.5%]
WolfSheep small 🔴 +5.3% [+5.0%, +5.6%] 🔴 +4.7% [+4.4%, +5.0%]
WolfSheep large 🔵 +1.9% [+1.3%, +2.5%] 🔴 +4.5% [+3.2%, +5.9%]
BoidFlockers small 🔵 +1.4% [+0.8%, +2.0%] 🔵 -0.7% [-0.9%, -0.4%]
BoidFlockers large 🔵 +0.3% [-0.3%, +0.9%] 🔵 -1.9% [-2.1%, -1.6%]

@quaquel quaquel added experimental Release notes label enhancement Release notes label labels Jan 16, 2026
@quaquel
Copy link
Copy Markdown
Member

quaquel commented Jan 16, 2026

I ran some quick tests locally. It seems this implementation is much faster because it eliminates significant overhead. I also think the API is much cleaner. I'll try to review in more detail soon. In the meantime, can you check the code coverage report and see if you can add additional tests to ensure we have close to 100% coverage?

@codebreaker32
Copy link
Copy Markdown
Collaborator Author

can you check the code coverage report and see if you can add additional tests to ensure we have close to 100% coverage?

Done

@quaquel quaquel merged commit 920d675 into mesa:main Jan 17, 2026
14 checks passed
@quaquel
Copy link
Copy Markdown
Member

quaquel commented Jan 17, 2026

Thanks again for this PR. A very nice improvement.

quaquel pushed a commit to quaquel/mesa that referenced this pull request Jan 18, 2026
@codebreaker32 codebreaker32 deleted the signal/computable-computed branch February 17, 2026 16:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Release notes label experimental Release notes label

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants