Skip to content

Commit 915d622

Browse files
committed
perf: Cythonize autorun functionality, add awaitable wrapper, and introduce performance benchmarks.
1 parent d3c42f6 commit 915d622

File tree

10 files changed

+227702
-16800
lines changed

10 files changed

+227702
-16800
lines changed

CYTHON_README.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,19 @@ Performance comparison between the Pure Python baseline and the Hyper-Optimized
2929
3030
The **4.65x speedup** for subscribers is a result of "Hyper Optimization" (Phase 8), which eliminated 66% of the overhead associated with checking for coroutines in synchronous listeners.
3131

32+
## Autorun Optimization (Phase 9)
33+
34+
In Phase 9, we fully Cythonized the `Autorun` class, embedding it directly within `_store_core.pyx` to access internal store state efficiently.
35+
36+
| Test Case | Baseline (Python) | Optimized (Cython) | Speedup |
37+
|-----------|-------------------|--------------------|-------------|
38+
| **Autorun Creation** | 52.6 μs | 15.5 μs | **3.40x** |
39+
| **Reactivity Check** | 9.6 μs | 5.6 μs | **1.71x** |
40+
| **Complex Selector** | 9.7 μs | 5.9 μs | **1.64x** |
41+
| **Notifications** | 668 μs | 383 μs | **1.74x** |
42+
43+
This provides substantial improvements for applications that rely heavily on reactive state derived from the store.
44+
3245
## Build & Reproduction
3346

3447
To reproduce these results, you can build the extension and run the benchmarks.
@@ -64,4 +77,5 @@ pytest-benchmark compare baseline.json optimized.json
6477
- `redux/_store_core.pyx`: The optimized Cython `Store` implementation.
6578
- `redux/_store_py.py`: The pure Python fallback.
6679
- `redux/main.py`: The selector module that handles the import logic.
67-
- `benchmarks/bench_dispatch.py`: The performance test suite.
80+
- `benchmarks/bench_dispatch.py`: The performance test suite for dispatch.
81+
- `benchmarks/bench_autorun.py`: The performance test suite for Autorun.

benchmarks/bench_autorun.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
2+
import pytest
3+
from redux.main import Store
4+
from redux.basic_types import BaseAction, StoreOptions
5+
from dataclasses import replace, field
6+
from immutable import Immutable
7+
8+
class State(Immutable):
9+
value: int
10+
nested: dict = field(default_factory=dict)
11+
12+
class IncrementAction(BaseAction):
13+
pass
14+
15+
def reducer(state, action):
16+
if state is None:
17+
return State(value=0)
18+
if isinstance(action, IncrementAction):
19+
return replace(state, value=state.value + 1)
20+
return state
21+
22+
@pytest.fixture
23+
def store():
24+
return Store(reducer, options=StoreOptions(auto_init=True))
25+
26+
def test_autorun_creation(benchmark, store):
27+
"""Benchmark creating autoruns."""
28+
29+
def run():
30+
@store.autorun(lambda s: s.value)
31+
def _(val):
32+
pass
33+
34+
benchmark(run)
35+
36+
def test_autorun_reactivity(benchmark, store):
37+
"""Benchmark autorun reaction overhead."""
38+
39+
@store.autorun(lambda s: s.value)
40+
def _(val):
41+
pass
42+
43+
def run():
44+
store.dispatch(IncrementAction())
45+
46+
benchmark(run)
47+
48+
def test_autorun_complex_selector(benchmark, store):
49+
"""Benchmark autorun with complex selector."""
50+
51+
@store.autorun(lambda s: s.value * 2 + (s.nested.get('a', 0) or 0))
52+
def _(val):
53+
pass
54+
55+
def run():
56+
store.dispatch(IncrementAction())
57+
58+
benchmark(run)
59+
60+
def test_autorun_many_subscribers(benchmark, store):
61+
"""Benchmark notification of many autoruns."""
62+
63+
for _ in range(100):
64+
@store.autorun(lambda s: s.value)
65+
def _(val):
66+
pass
67+
68+
def run():
69+
store.dispatch(IncrementAction())
70+
71+
benchmark(run)

0 commit comments

Comments
 (0)