Performance Timing
Demonstrates c2py23's built-in performance timing instrumentation. Two overloads (double and float) show per-variant timing breakdown.
Interface
# Python dict format equivalent of wsum.c2py
{
"module": "timing_demomod",
"source": ["wsum.c"],
"timing": True,
"functions": [
{
"py_sig": "wsum(data: buffer, weight: float) -> float",
"doc": "Weighted sum with automatic dispatch. Supports double and float buffers.",
"c_overloads": [
{
"sig": "weighted_sum_double(const double *data, intptr_t n, float weight) -> double",
"map": {
"data": "data.ptr",
"n": "data.n",
"weight": "weight",
},
"when": "data.format == 'd'",
"name": "double",
},
{
"sig": "weighted_sum_float(const float *data, intptr_t n, float weight) -> double",
"map": {
"data": "data.ptr",
"n": "data.n",
"weight": "weight",
},
"when": "data.format == 'f'",
"name": "float",
},
],
"default_raise": "TypeError: expected float or double buffer",
},
],
}
C Source
#include <stdint.h>
double weighted_sum_double(const double *data, intptr_t n, float weight) {
double total = 0.0;
intptr_t i;
for (i = 0; i < n; i++) {
total += data[i] * (double)weight;
}
return total;
}
double weighted_sum_float(const float *data, intptr_t n, float weight) {
double total = 0.0;
intptr_t i;
for (i = 0; i < n; i++) {
total += (double)data[i] * (double)weight;
}
return total;
}
Jupyter Notebook
The interactive notebook examples/timing_demo/timing_demo.ipynb demonstrates:
- Reading timing data with
c2py23.perf.read_perf() - Per-function vs per-overload timing breakdown
- Comparing c2py23 timing with
%%timecell magic - Switching tick source: wall-clock (default) vs CPU cycle counter
- Dynamically enabling/disabling timing per function
Build & Run
pip install -e . # from repo root
cd examples/timing_demo
c2py23 wsum.c2py -o wsummod_wrapper.c
python -c "
import ctypes
import timing_demomod as tmod
data = (ctypes.c_double * 5)(1.0, 2.0, 3.0, 4.0, 5.0)
r = tmod.wsum(data, 2.0)
print('Sum:', r)
from c2py23.perf import read_perf
print('Timing:', read_perf(tmod.wsum))
"
How It Works
timing: true enables per-function performance counters. Two c2py_perf_t
structs are emitted per function: one for the wrapper overhead and one for
each overload's C code. Ticks are recorded without any Python-side
interaction -- the wrapper reads the cycle counter or clock_gettime
before and after the C call.
The tick source defaults to nanosecond-resolution wall-clock. Switch to CPU cycle counter for higher precision:
Fall back to wall-clock:
When timing is disabled (set_enabled(func, 0)), the tick counters are
bypassed entirely -- zero overhead.