Skip to content

Commit 25ea6a9

Browse files
authored
Add benchmark test suite for model operations (#798)
* Add benchmark test suite for model operations * Add benchmark job to CI with summary reporting * Fix benchmark summary output to GitHub step summary * Output benchmark table to both logs and step summary
1 parent 23548bf commit 25ea6a9

5 files changed

Lines changed: 729 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,82 @@ jobs:
9494
flags: unit
9595
env_vars: OS
9696
fail_ci_if_error: false
97+
98+
benchmark:
99+
name: Benchmarks
100+
needs: lint
101+
runs-on: ubuntu-latest
102+
timeout-minutes: 10
103+
services:
104+
redis:
105+
image: redis/redis-stack:latest
106+
ports:
107+
- 6379:6379
108+
options: >-
109+
--health-cmd "redis-cli ping"
110+
--health-interval 10s
111+
--health-timeout 5s
112+
--health-retries 5
113+
steps:
114+
- name: Checkout
115+
uses: actions/checkout@v6
116+
- name: Install uv
117+
uses: astral-sh/setup-uv@v7
118+
- name: Setup Python ${{ env.pythonversion }}
119+
uses: actions/setup-python@v6
120+
with:
121+
python-version: ${{ env.pythonversion }}
122+
- name: Install dependencies
123+
run: uv sync
124+
- name: Make sync version of library (redis_om)
125+
run: make sync
126+
- name: Run benchmarks
127+
env:
128+
REDIS_OM_URL: "redis://localhost:6379?decode_responses=True"
129+
run: |
130+
uv run pytest tests/test_benchmarks.py -v --benchmark-only --benchmark-json=benchmark-results.json
131+
- name: Upload benchmark results
132+
uses: actions/upload-artifact@v4
133+
with:
134+
name: benchmark-results
135+
path: benchmark-results.json
136+
- name: Display benchmark summary
137+
run: |
138+
# Generate the benchmark table
139+
uv run python << 'PYTHON_SCRIPT' > benchmark-table.txt
140+
import json
141+
print("## Benchmark Results")
142+
print("")
143+
print("| Test | Mean | Min | Max | OPS |")
144+
print("|------|------|-----|-----|-----|")
145+
with open('benchmark-results.json') as f:
146+
data = json.load(f)
147+
for b in data['benchmarks']:
148+
name = b['name'].replace('test_', '')
149+
mean = b['stats']['mean'] * 1e6 # convert to microseconds
150+
min_val = b['stats']['min'] * 1e6
151+
max_val = b['stats']['max'] * 1e6
152+
ops = b['stats']['ops']
153+
if mean < 1:
154+
mean_str = f'{mean*1000:.0f}ns'
155+
elif mean < 1000:
156+
mean_str = f'{mean:.1f}us'
157+
else:
158+
mean_str = f'{mean/1000:.1f}ms'
159+
if min_val < 1:
160+
min_str = f'{min_val*1000:.0f}ns'
161+
elif min_val < 1000:
162+
min_str = f'{min_val:.1f}us'
163+
else:
164+
min_str = f'{min_val/1000:.1f}ms'
165+
if max_val < 1:
166+
max_str = f'{max_val*1000:.0f}ns'
167+
elif max_val < 1000:
168+
max_str = f'{max_val:.1f}us'
169+
else:
170+
max_str = f'{max_val/1000:.1f}ms'
171+
print(f'| {name} | {mean_str} | {min_str} | {max_str} | {ops:.0f}/s |')
172+
PYTHON_SCRIPT
173+
# Output to both logs and step summary
174+
cat benchmark-table.txt
175+
cat benchmark-table.txt >> $GITHUB_STEP_SUMMARY

make_sync.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,14 @@ def main():
5454
additional_replacements=ADDITIONAL_REPLACEMENTS,
5555
),
5656
]
57+
# Files to exclude from sync generation (benchmarks require special async handling)
58+
excluded_files = {"test_benchmarks.py"}
59+
5760
filepaths = []
5861
for root, _, filenames in os.walk(base_dir):
5962
for filename in filenames:
63+
if filename in excluded_files:
64+
continue
6065
if filename.rpartition(".")[-1] in (
6166
"py",
6267
"pyi",
@@ -107,5 +112,7 @@ def remove_run_async_call(match):
107112
f.write(content)
108113

109114

115+
116+
110117
if __name__ == "__main__":
111118
main()

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ dev = [
7272
"pre-commit>=4.3.0; python_version >= '3.10'",
7373
"mkdocs>=1.6.1",
7474
"mkdocs-material>=9.7.1",
75+
"pytest-benchmark>=5.2.3",
7576
]
7677

7778
[build-system]

0 commit comments

Comments
 (0)