Backtest profile
Where the backtest spends its CPU. The hourly evaluation and the walk-forward replay run under callgrind, which counts every instruction executed, so the figures are exact and repeat run to run. Code the compiler inlined is put back under the function it came from. See how it is made.
Loading…
Flame graph
Open full sizeEach box is a function, as wide as its share of instructions, stacked on its caller. Click a box to zoom into it; search with Ctrl-F inside the full-size view.
Phases
What it found, and what changed, 28 October
The first profile found two hot spots. Both are fixed, with the trades unchanged: every pair's evaluation and trades on all 101 walked days came out identical before and after. The walk now takes 7.6 seconds instead of 52, and the same work runs on five times fewer instructions.
- The New York offset was 57% of the backtest.
time::ny_offsetworked out the year's daylight-saving dates from scratch each time it was asked, andmorning_breakoutasked for each of the last 100 bars on every bar it tested. The dates for 1970 to 2100 are now a table built when the crate compiles,morning_breakouttakes one offset for the whole session, and the market windows convert a bar's time once instead of four times. - Bars were validated again on every look: 18%.
entry::tailcheckedBar::is_validon the whole window each time a strategy looked, 108 bars formacd_crossover. Bars are now checked once, where they come in:seriesalready kept only valid bars, and the snapshot now drops any others.
What is left is spread out. The backtest loop itself is about half, macd_crossover and
morning_breakout are 18% each (MACD recomputes its averages over 108 bars on every bar), and
the other strategies are 3% or less. The walk-forward replay is still nearly all of it, as it evaluates every
pair afresh on the 60-day window before each walked day.
Measured on the synthetic market. A real history changes how often strategies signal, not where a bar's checks spend their time.
Hottest functions
Self: instructions in the function's own code. Total: with everything it calls, inlined or not. Hover a name for the whole of it.
| Function | Self | Total |
|---|
Hottest lines
| Line | Function | Share |
|---|
How it is made
A GitHub workflow reprofiles the backtest on every change to its code, on the hourly job's latest bars, and this page shows its newest result. By hand, on Linux with valgrind, from the repository root, on a history snapshot or, with no arguments, a synthetic market of the same shape (40 random-walk symbols over 180 days):
scripts/profile.sh data/history-180.bin
scripts/profile.sh
A native run times the phases. A callgrind run of the last eight walked days counts the
instructions: every walked day is the same work, so the shares hold for the whole walk. The binary's debug
information names the functions the compiler inlined, and each call's site says which inlined function made
it. The script writes flamegraph.svg and profile.json; a copy deployed with the
site is shown until the workflow has run.