Deterministic operation counters for audio-callback cost gates. More...
#include <atomic>#include <cmath>#include <complex>#include <cstdint>Go to the source code of this file.
Classes | |
| struct | pulp::signal::rt::RtWorkCounts |
| A snapshot (or a difference of two snapshots) of the counted operations. More... | |
| class | pulp::signal::rt::RtWorkCounter |
| Measures the counted work done between construction and delta(). More... | |
Namespaces | |
| namespace | pulp |
| namespace | pulp::signal |
| namespace | pulp::signal::rt |
| namespace | pulp::signal::rt::detail |
Macros | |
| #define | PULP_RT_WORK_COUNTERS 0 |
Functions | |
| void | pulp::signal::rt::count_fft () noexcept |
| Record one FFT execution. | |
| void | pulp::signal::rt::count_trig (std::uint64_t n=1) noexcept |
| Record n transcendental evaluations. | |
| void | pulp::signal::rt::count_bins (std::uint64_t n) noexcept |
| Record n units of per-bin accumulation work. | |
| RtWorkCounts | pulp::signal::rt::work_counts () noexcept |
| Current process-wide totals. | |
| template<typename T> | |
| std::complex< T > | pulp::signal::rt::polar (T magnitude, T phase) noexcept |
| Counted std::polar. Bit-identical result. | |
| template<typename T> | |
| T | pulp::signal::rt::sin (T x) noexcept |
| Counted std::sin. Bit-identical result. | |
| template<typename T> | |
| T | pulp::signal::rt::cos (T x) noexcept |
| Counted std::cos. Bit-identical result. | |
| template<typename T> | |
| T | pulp::signal::rt::exp (T x) noexcept |
| Counted std::exp. Bit-identical result. | |
| template<typename T> | |
| T | pulp::signal::rt::arg (const std::complex< T > &z) noexcept |
| Counted std::arg (an atan2). Bit-identical result. | |
Variables | |
| constexpr bool | pulp::signal::rt::kWorkCountersEnabled = 0 != 0 |
| True when this build counts operations. | |
Deterministic operation counters for audio-callback cost gates.
Offline renders have no deadline, so a callback that bursts expensive work on a state transition (a latch, a mode switch, a preset load) renders perfectly offline and drops a buffer in a DAW. Wall-clock timing can see that burst but flakes on shared runners; counting the expensive operations cannot flake. These counters are what a required-lane transition gate reads.
Counted operations:
Build contract: counting compiles in only when PULP_RT_WORK_COUNTERS is non-zero. The root CMake option of the same name defines it for every translation unit of a build at once (default: ON when tests are built, OFF otherwise), so the inline hooks below never disagree between TUs. With the option OFF every hook is an empty inline function and the wrappers are the bare std:: calls.
Storage is process-wide relaxed atomics rather than thread-locals: on Darwin the first access to a thread_local from a new thread can allocate, which would put a malloc on the first audio callback of a counted build. The consequence is attribution: a delta measured around a callback includes work done concurrently on other threads. Gates therefore measure a single-threaded offline render, where the render thread is the only thread doing counted work.
RT contract: every hook is one relaxed fetch_add (or nothing); no allocation, no lock. work_counts() is a handful of relaxed loads.
| #define PULP_RT_WORK_COUNTERS 0 |