vor 0.2.1

Cross-platform performance instrumentation with an in-app egui panel and live system and GPU metrics.
Documentation
//! Cross-platform performance instrumentation.
//!
//! Tag a function with `#[vor::profile]`, a whole `impl` with
//! `#[vor::all_functions]`, or open a scoped block with
//! [`profile_scope!`]. Each tag emits a `puffin` scope (frame-buffer
//! source for an in-app flame chart), a `tracing` span (sink source:
//! Chrome-trace file on `mac`, DevTools timeline on `web`), and —
//! under the `cuda` feature — an NVTX range for NVIDIA Nsight Systems.
//!
//! Frame boundaries: call [`frame_mark`] once per rendered frame so
//! puffin can group scopes by frame.

#[cfg(feature = "web")]
mod browser;
mod calibrate;
#[cfg(feature = "mac")]
mod chrome;
mod frame;
mod gpu;
mod io_acc;
mod macros;
mod mem;
mod metrics_acc;
// Capture writes files on a background thread; neither is available on
// wasm, where VOR_RECORD is never set anyway.
#[cfg(not(target_arch = "wasm32"))]
mod record;
mod scope;
mod sink;
mod system;
#[cfg(feature = "viz")]
pub mod viz;

pub use vor_macros::{all_functions, profile, skip};

#[doc(hidden)]
pub use puffin as __priv_puffin;
#[doc(hidden)]
pub use tracing as __priv_tracing;

/// NVTX range guard the profiling macros open alongside their puffin
/// scope, so instrumented code also shows up on an NVIDIA Nsight
/// Systems timeline.
///
/// Real under the `cuda` feature; a zero-sized no-op otherwise, so
/// the macros can emit the call unconditionally.
#[cfg(feature = "cuda")]
#[doc(hidden)]
#[must_use = "bind the guard so the NVTX range stays open for the scope"]
pub struct __NvtxRange {
    _guard: nvtx::RangeGuard,
}

#[cfg(feature = "cuda")]
#[doc(hidden)]
pub fn __nvtx_range(name: &str) -> __NvtxRange {
    __NvtxRange {
        _guard: nvtx::range!("{name}"),
    }
}

#[cfg(not(feature = "cuda"))]
#[doc(hidden)]
pub struct __NvtxRange;

#[cfg(not(feature = "cuda"))]
#[doc(hidden)]
pub const fn __nvtx_range(_name: &str) -> __NvtxRange {
    __NvtxRange
}

#[cfg(feature = "web")]
pub use crate::browser::BrowserSink;
pub use crate::calibrate::{calibrate, empty_span_ns};
#[cfg(feature = "mac")]
pub use crate::chrome::ChromeTraceSink;
pub use crate::frame::FrameStats;
pub use crate::io_acc::{IoTick, drain as drain_io, record as record_io};
pub use crate::mem::current_memory_bytes;
pub use crate::metrics_acc::{record_metric, record_metric_unit};
#[cfg(not(target_arch = "wasm32"))]
pub use crate::record::read::{Frame, MetricColumn, Reader};
pub use crate::scope::{ScopeGuard, scope};
pub use crate::sink::{Guard, Sink};
pub use crate::system::SystemSample;

/// Turn on puffin scope collection process-wide.
///
/// Until enabled, every [`profile`] / [`profile_scope!`] expansion's
/// puffin half is a no-op; the tracing half is unaffected.
///
/// Also arms the headless recorder when `VOR_RECORD` is set, so an ML
/// job records by setting one env var and changing nothing else.
pub fn enable() {
    puffin::set_scopes_on(true);
    #[cfg(not(target_arch = "wasm32"))]
    crate::record::arm();
}

/// Block until every captured frame is written to the `VOR_RECORD`
/// stream. No-op when not recording. Call before exit so a reader sees
/// the run's final frames.
#[cfg(not(target_arch = "wasm32"))]
pub fn flush_recording() {
    crate::record::flush();
}

/// Mark a frame boundary in puffin's ring buffer.
///
/// Required for the flame UI to slice scopes into frame-sized
/// columns. Pair with [`drain_io`] to harvest the same frame's I/O
/// totals.
///
/// When the recorder is armed ([`enable`] with `VOR_RECORD` set), this
/// also captures the just-closed frame to the stream.
pub fn frame_mark() {
    puffin::GlobalProfiler::lock().new_frame();
    #[cfg(not(target_arch = "wasm32"))]
    crate::record::on_frame_mark();
}