Skip to content

aowlspt_drainprof.h

Source: abi/aowlspt_drainprof.h — 276 lines, 26 file-scope functions.

What this header owns

Reproduced verbatim from the header's own banner comment — these notes are frequently the only written record of why the subsystem is shaped the way it is.

text
 aowlspt_drainprof.h -- THE DRAIN PROFILER. A per-rider QPC bracket over every
rider on the host's two per-frame drains, so "where does the frame go" is
answered by reading ONE log line instead of relaunching the game.

WHY THIS EXISTS, measured. `abi/aowlspt_frametime.h` established the fact:
87.4-92.2ms/frame in raid (phase-verified DEPLOYED in the same log) against
26.7ms in the menu. It cannot say WHICH of the fourteen riders on
`TarkovApplication::Update` and the three on the render drain is spending it.
Four bisection attempts by relaunching with features toggled produced one
RETRACTED claim; removing ~11ms of real, measured work (the nuFn/duFn
per-call verify preamble) moved the frame only 92.2 -> 87.4ms, which is not a
result any toggle experiment can explain. So: bracket everything, at once, in
one run.

WHAT IT HOOKS. Nothing new. It installs NO detour, resolves NO name, calls
NOTHING in the game and dereferences no game pointer. It is a pair of QPC
reads around call sites that already exist, in `patchFired`'s `gDrainSlot`
and `gRenderDrainSlot` branches, plus one pair around `cInvokeCallback` in
`runDue` for the per-mod breakdown.

IT ARMS NO SEH GUARD, deliberately and for the same reason the frame meter
does not: its entire working set is the statics in this file plus
QueryPerformanceCounter. More important, `aowl_p_p_seh` is NOT RE-ENTRANT --
several of the riders it brackets (natEspDrainTick, camDrainTick,
cwDrainTick, rpDrainTick) open one internally, and a guard here would be
OUTSIDE theirs, which is where a bracket belongs, but a guard nested the
other way would disarm the outer one. So: no guard, ever, in this file.

DISJOINT AND EXHAUSTIVE, by construction and then by arithmetic.
  - The TOP-LEVEL rows (slot 0..AOWL_DP_TOP-1) bracket sequential,
    non-overlapping statements. They cannot double-count.
  - The NESTED rows (slot AOWL_DP_TOP..) are per-mod callback times measured
    INSIDE `mainDrain`. They are a BREAKDOWN OF row 1, not additional cost,
    and the reporter must never add them to the top-level sum.
  - `aowl_dp_frame()` accumulates the interval between successive drain
    entries -- the same clock, the same place in the tick as the frame meter
    -- so `accounted% = sum(top-level) / frame_ns` is computed against a
    denominator this file measured itself and does not borrow.
  - Whatever is left is OUTSIDE every bracket and the reporter is required to
    say so in those words. It is not "the rest of the host"; it is the game.

THE POSITIVE CONTROL, slot AOWL_DP_CTRL. 512 dependent integer adds, run in
the same tick, through the same bracket, with the same clock. Its expected
cost is on the order of a few hundred nanoseconds on this machine; if the
control reads 0us or reads milliseconds, THE METER IS LYING and every other
row in the line is void. Tonight a control settled exactly this question and
disproved the theory that produced it. The adds are accumulated into a
volatile sink so no compiler may delete them.

UNITS. Every accumulator is NANOSECONDS internally and every printed number
is MICROSECONDS with the letters `us` attached, because `neUs()` output was
read as nanoseconds tonight and sent an agent chasing a phantom. There is no
unitless number anywhere in the output.

NO SENTINEL IS EVER PRINTED AS A VALUE. There are no percentiles here and so
no saturation marker; every row is a total and a call count, and a row with
zero calls prints `0 calls` rather than a duration of zero.

THE METER'S OWN OVERHEAD IS MEASURED, not asserted. At enable time
`aowl_dp_calibrate()` runs AOWL_DP_CAL empty bracket pairs and stores the
per-pair cost, which the reporter prints and multiplies by the observed call
count so a reader can see the instrument's share of its own reading.

THREE OUTCOMES. Below AOWL_DP_MIN_FRAMES bracketed frames the reporter is
required to say INCONCLUSIVE. "Not enough frames" is not a pass.

Constants

  • AOWLSPT_DRAINPROF_H
  • AOWL_DP_AUTORAID
  • AOWL_DP_CAL
  • AOWL_DP_CAM
  • AOWL_DP_CTRL
  • AOWL_DP_CTRL_ITERS
  • AOWL_DP_CURSOR
  • AOWL_DP_CW
  • AOWL_DP_FT
  • AOWL_DP_INSPECT
  • AOWL_DP_MAIN
  • AOWL_DP_MIN_FRAMES
  • AOWL_DP_MOD0
  • AOWL_DP_MODESKIP
  • AOWL_DP_MODOTHER
  • AOWL_DP_NATESP
  • AOWL_DP_NATRAID
  • AOWL_DP_NMOD
  • AOWL_DP_RAIDPHASE
  • AOWL_DP_RCAM
  • AOWL_DP_RCURSOR
  • AOWL_DP_RDRAIN
  • AOWL_DP_SLOTS
  • AOWL_DP_SPLREBR
  • AOWL_DP_TOP
  • AOWL_DP_UISTATE

Functions

SignatureLine
int aowl_dp_init_qpf(void)131
int64_t aowl_dp_now(void)142
void aowl_dp_add(int32_t slot, int64_t t0)149
void aowl_dp_frame(void)169
void aowl_dp_control_body(void)189
void aowl_dp_calibrate(void)196
void aowl_dp_reset(void)214
void aowl_dp_set_enabled(int32_t on)222
int32_t aowl_dp_enabled(void)231
int32_t aowl_dp_mod_slot(int32_t modIndex)238
int64_t aowl_dp_ns(int32_t i)245
int64_t aowl_dp_calls(int32_t i)248
int64_t aowl_dp_max(int32_t i)251
int64_t aowl_dp_frames(void)254
int64_t aowl_dp_frame_ns(void)255
int64_t aowl_dp_dropped(void)256
int64_t aowl_dp_overhead(void)257
int32_t aowl_dp_top(void)258
int32_t aowl_dp_slots(void)259
int32_t aowl_dp_mod0(void)260
int32_t aowl_dp_modother(void)261
int32_t aowl_dp_ctrl(void)262
int32_t aowl_dp_ctrl_iters(void)263
int64_t aowl_dp_min_frames(void)264
int32_t aowl_dp_cal(void)265
int64_t aowl_dp_accounted_ns(void)269

aoughwl — self-hosted platform for things n stuff. Contact / Support on Discord for access to the private backends.