Skip to content

Commit 6f67ce8

Browse files
petercorkeclaude
authored andcommitted
feat(benchmarks): print machine and version summary before results
CPU, OS, Python, numpy and spatialmath versions and the timing settings, so a pasted table is self-describing. Modeled on RTB's rne_speed.py. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 9981dbc commit 6f67ce8

1 file changed

Lines changed: 77 additions & 1 deletion

File tree

‎benchmarks/benchmark_smtb.py‎

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,95 @@
11
#!/usr/bin/env python3
22
# -*- coding: utf-8 -*-
33
"""
4+
Micro-benchmarks for spatialmath: base functions and classes for SO(3),
5+
SE(3), quaternions and twists, plus a NumPy baseline. Run from a checkout::
6+
7+
python benchmarks/benchmark_smtb.py
8+
9+
The output starts with a summary of the machine and package versions, so a
10+
pasted table is self-describing.
11+
412
Created on Fri Apr 10 14:22:36 2020
513
614
@author: Peter Corke
715
"""
816

9-
17+
import os
18+
import platform
19+
import subprocess
1020
import timeit as _timeit
21+
22+
import numpy as np
1123
from ansitable import ANSITable, Column
1224

25+
import spatialmath
26+
1327
N = 10_000
1428
REPEATS = 5
1529

1630
table = None
1731

1832

33+
def cpu_info() -> str:
34+
"""Best-effort, portable one-line CPU description
35+
36+
:return: CPU name and core count, plus clock speed if available
37+
:rtype: str
38+
39+
No new hard dependency: psutil is used for clock speed only if already
40+
installed. Some platforms (e.g. Apple Silicon) don't expose a single
41+
meaningful clock speed, so a missing or nonsensical reading is omitted.
42+
"""
43+
system = platform.system()
44+
name = None
45+
46+
if system == "Darwin":
47+
try:
48+
name = subprocess.check_output(
49+
["sysctl", "-n", "machdep.cpu.brand_string"], text=True
50+
).strip()
51+
except Exception:
52+
pass
53+
elif system == "Linux":
54+
try:
55+
with open("/proc/cpuinfo") as f:
56+
for line in f:
57+
if line.lower().startswith("model name"):
58+
name = line.split(":", 1)[1].strip()
59+
break
60+
except Exception:
61+
pass
62+
elif system == "Windows":
63+
name = platform.processor() or None
64+
65+
if not name:
66+
name = platform.processor() or platform.machine() or "unknown CPU"
67+
68+
info = f"{name} ({os.cpu_count() or '?'} cores)"
69+
70+
try:
71+
import psutil
72+
73+
freq = psutil.cpu_freq()
74+
# real clock speeds are hundreds to thousands of MHz; some platforms
75+
# report bogus single-digit values instead of raising
76+
if freq and freq.max and freq.max > 100:
77+
info += f", {freq.max:.0f} MHz"
78+
except Exception:
79+
pass
80+
81+
return info
82+
83+
84+
def print_machine_summary() -> None:
85+
print(f"CPU: {cpu_info()}")
86+
print(f"OS: {platform.platform()}")
87+
print(f"Python: {platform.python_version()}")
88+
print(f"numpy: {np.__version__}")
89+
print(f"spatialmath: {spatialmath.__version__}")
90+
print(f"Timing: min of {REPEATS} repeats x {N} calls")
91+
92+
1993
def new_table():
2094
return ANSITable(
2195
Column("Operation", headalign="^"),
@@ -41,6 +115,8 @@ def section(title):
41115
table = new_table()
42116

43117

118+
print_machine_summary()
119+
44120
# ------------------------------------------------------------------------- #
45121
transforms_setup = '''
46122
from spatialmath import SE3

0 commit comments

Comments
 (0)