libdictenstein 4.0.0-rc.3

High-performance dictionary data structures (trie, DAWG, double-array trie, suffix automaton, lock-free durable persistent ART) behind one trait API; pairs with liblevenshtein for fuzzy matching
//! Feature-gated construction counters for causal performance investigations.

#![allow(dead_code)]

#[cfg(feature = "perf-instrumentation")]
use std::sync::atomic::{AtomicU64, Ordering};

/// Logical work generated by lock-free dynamic-DAWG construction.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct CausalConstructionStats {
    /// Term insertions requested by constructors or callers.
    pub term_insert_attempts: u64,
    /// Input units across requested term insertions.
    pub input_units: u64,
    /// Published graph versions loaded by insertion CAS loops.
    pub version_loads: u64,
    /// Key units traversed while locating rewrite paths.
    pub path_units_walked: u64,
    /// Immutable edge lists cloned during path copying.
    pub edge_lists_cloned: u64,
    /// Child `Arc` references cloned with those edge lists.
    pub edge_arcs_cloned: u64,
    /// Immutable nodes allocated, including temporary missing-path nodes.
    pub nodes_created: u64,
    /// Immutable nodes physically destroyed.
    pub nodes_dropped: u64,
    /// Candidate graph-version objects created.
    pub graph_versions_created: u64,
    /// Graph versions successfully published by CAS.
    pub cas_publications: u64,
    /// Failed publication attempts retried after contention.
    pub cas_retries: u64,
    /// Constructor-owned batch sorts.
    pub batch_sort_calls: u64,
    /// Terms submitted to constructor-owned batch sorts.
    pub batch_sort_terms: u64,
    /// Units submitted to constructor-owned batch sorts.
    pub batch_sort_units: u64,
    /// Immutable traversal snapshots created.
    pub resource_snapshots_created: u64,
    /// Snapshot-arena directory-growth mutex acquisitions.
    pub resource_arena_locks: u64,
    /// Snapshot finality operations.
    pub resource_is_final_calls: u64,
    /// Snapshot value operations.
    pub resource_value_calls: u64,
    /// Immutable native graphs projected into the compact ABI representation.
    pub resource_graph_projections: u64,
    /// Compact graph views acquired through the optional graph interface.
    pub resource_graph_calls: u64,
    /// Values resolved through compact-graph value cursors.
    pub resource_graph_value_calls: u64,
    /// Snapshot edge-list operations.
    pub resource_edges_calls: u64,
    /// First edge expansions for snapshot nodes.
    pub resource_edge_cache_misses: u64,
    /// Native dictionary edges enumerated into snapshot arenas.
    pub resource_native_edges_enumerated: u64,
    /// Nodes appended to snapshot arenas, including roots.
    pub resource_nodes_materialized: u64,
    /// Cached edge descriptors cloned for provider callbacks.
    pub resource_descriptors_cloned: u64,
    /// Snapshot nodes synchronously reclaimed with their final arena owner.
    pub resource_nodes_reclaimed: u64,
    /// Total nanoseconds spent synchronously reclaiming snapshot arenas.
    pub resource_reclaim_nanos: u64,
    /// Longest observed synchronous snapshot-arena reclamation in nanoseconds.
    pub resource_reclaim_max_nanos: u64,
}

#[cfg(feature = "perf-instrumentation")]
macro_rules! counter {
    ($name:ident) => {
        static $name: AtomicU64 = AtomicU64::new(0);
    };
}

#[cfg(feature = "perf-instrumentation")]
counter!(TERM_INSERT_ATTEMPTS);
#[cfg(feature = "perf-instrumentation")]
counter!(INPUT_UNITS);
#[cfg(feature = "perf-instrumentation")]
counter!(VERSION_LOADS);
#[cfg(feature = "perf-instrumentation")]
counter!(PATH_UNITS_WALKED);
#[cfg(feature = "perf-instrumentation")]
counter!(EDGE_LISTS_CLONED);
#[cfg(feature = "perf-instrumentation")]
counter!(EDGE_ARCS_CLONED);
#[cfg(feature = "perf-instrumentation")]
counter!(NODES_CREATED);
#[cfg(feature = "perf-instrumentation")]
counter!(NODES_DROPPED);
#[cfg(feature = "perf-instrumentation")]
counter!(GRAPH_VERSIONS_CREATED);
#[cfg(feature = "perf-instrumentation")]
counter!(CAS_PUBLICATIONS);
#[cfg(feature = "perf-instrumentation")]
counter!(CAS_RETRIES);
#[cfg(feature = "perf-instrumentation")]
counter!(BATCH_SORT_CALLS);
#[cfg(feature = "perf-instrumentation")]
counter!(BATCH_SORT_TERMS);
#[cfg(feature = "perf-instrumentation")]
counter!(BATCH_SORT_UNITS);
#[cfg(feature = "perf-instrumentation")]
counter!(RESOURCE_SNAPSHOTS_CREATED);
#[cfg(feature = "perf-instrumentation")]
counter!(RESOURCE_ARENA_LOCKS);
#[cfg(feature = "perf-instrumentation")]
counter!(RESOURCE_IS_FINAL_CALLS);
#[cfg(feature = "perf-instrumentation")]
counter!(RESOURCE_VALUE_CALLS);
#[cfg(feature = "perf-instrumentation")]
counter!(RESOURCE_GRAPH_PROJECTIONS);
#[cfg(feature = "perf-instrumentation")]
counter!(RESOURCE_GRAPH_CALLS);
#[cfg(feature = "perf-instrumentation")]
counter!(RESOURCE_GRAPH_VALUE_CALLS);
#[cfg(feature = "perf-instrumentation")]
counter!(RESOURCE_EDGES_CALLS);
#[cfg(feature = "perf-instrumentation")]
counter!(RESOURCE_EDGE_CACHE_MISSES);
#[cfg(feature = "perf-instrumentation")]
counter!(RESOURCE_NATIVE_EDGES_ENUMERATED);
#[cfg(feature = "perf-instrumentation")]
counter!(RESOURCE_NODES_MATERIALIZED);
#[cfg(feature = "perf-instrumentation")]
counter!(RESOURCE_DESCRIPTORS_CLONED);
#[cfg(feature = "perf-instrumentation")]
counter!(RESOURCE_NODES_RECLAIMED);
#[cfg(feature = "perf-instrumentation")]
counter!(RESOURCE_RECLAIM_NANOS);
#[cfg(feature = "perf-instrumentation")]
counter!(RESOURCE_RECLAIM_MAX_NANOS);

#[inline(always)]
fn add(counter: Counter, value: u64) {
    #[cfg(feature = "perf-instrumentation")]
    counter.fetch_add(value, Ordering::Relaxed);
    #[cfg(not(feature = "perf-instrumentation"))]
    let _ = (counter, value);
}

#[cfg(feature = "perf-instrumentation")]
type Counter = &'static AtomicU64;
#[cfg(not(feature = "perf-instrumentation"))]
type Counter = ();

macro_rules! recorder {
    ($function:ident, $counter:ident) => {
        #[inline(always)]
        pub(crate) fn $function(value: u64) {
            #[cfg(feature = "perf-instrumentation")]
            add(&$counter, value);
            #[cfg(not(feature = "perf-instrumentation"))]
            add((), value);
        }
    };
}

recorder!(record_term_insert_attempts, TERM_INSERT_ATTEMPTS);
recorder!(record_input_units, INPUT_UNITS);
recorder!(record_version_loads, VERSION_LOADS);
recorder!(record_path_units_walked, PATH_UNITS_WALKED);
recorder!(record_edge_lists_cloned, EDGE_LISTS_CLONED);
recorder!(record_edge_arcs_cloned, EDGE_ARCS_CLONED);
recorder!(record_nodes_created, NODES_CREATED);
recorder!(record_nodes_dropped, NODES_DROPPED);
recorder!(record_graph_versions_created, GRAPH_VERSIONS_CREATED);
recorder!(record_cas_publications, CAS_PUBLICATIONS);
recorder!(record_cas_retries, CAS_RETRIES);
recorder!(record_batch_sort_calls, BATCH_SORT_CALLS);
recorder!(record_batch_sort_terms, BATCH_SORT_TERMS);
recorder!(record_batch_sort_units, BATCH_SORT_UNITS);
recorder!(
    record_resource_snapshots_created,
    RESOURCE_SNAPSHOTS_CREATED
);
recorder!(record_resource_arena_locks, RESOURCE_ARENA_LOCKS);
recorder!(record_resource_is_final_calls, RESOURCE_IS_FINAL_CALLS);
recorder!(record_resource_value_calls, RESOURCE_VALUE_CALLS);
recorder!(
    record_resource_graph_projections,
    RESOURCE_GRAPH_PROJECTIONS
);
recorder!(record_resource_graph_calls, RESOURCE_GRAPH_CALLS);
recorder!(
    record_resource_graph_value_calls,
    RESOURCE_GRAPH_VALUE_CALLS
);
recorder!(record_resource_edges_calls, RESOURCE_EDGES_CALLS);
recorder!(
    record_resource_edge_cache_misses,
    RESOURCE_EDGE_CACHE_MISSES
);
recorder!(
    record_resource_native_edges_enumerated,
    RESOURCE_NATIVE_EDGES_ENUMERATED
);
recorder!(
    record_resource_nodes_materialized,
    RESOURCE_NODES_MATERIALIZED
);
recorder!(
    record_resource_descriptors_cloned,
    RESOURCE_DESCRIPTORS_CLONED
);
recorder!(record_resource_nodes_reclaimed, RESOURCE_NODES_RECLAIMED);
recorder!(record_resource_reclaim_nanos, RESOURCE_RECLAIM_NANOS);

#[inline(always)]
pub(crate) fn record_resource_reclaim_max_nanos(value: u64) {
    #[cfg(feature = "perf-instrumentation")]
    RESOURCE_RECLAIM_MAX_NANOS.fetch_max(value, Ordering::Relaxed);
    #[cfg(not(feature = "perf-instrumentation"))]
    let _ = value;
}

/// Reset all construction counters to zero.
#[cfg(feature = "perf-instrumentation")]
pub fn reset_causal_construction_stats() {
    for counter in counters() {
        counter.store(0, Ordering::Relaxed);
    }
}

/// No-op reset for timing/profile builds where counters are compiled out.
#[cfg(not(feature = "perf-instrumentation"))]
pub fn reset_causal_construction_stats() {}

/// Snapshot all construction counters.
#[cfg(feature = "perf-instrumentation")]
pub fn causal_construction_stats() -> CausalConstructionStats {
    let load = |counter: &AtomicU64| counter.load(Ordering::Relaxed);
    CausalConstructionStats {
        term_insert_attempts: load(&TERM_INSERT_ATTEMPTS),
        input_units: load(&INPUT_UNITS),
        version_loads: load(&VERSION_LOADS),
        path_units_walked: load(&PATH_UNITS_WALKED),
        edge_lists_cloned: load(&EDGE_LISTS_CLONED),
        edge_arcs_cloned: load(&EDGE_ARCS_CLONED),
        nodes_created: load(&NODES_CREATED),
        nodes_dropped: load(&NODES_DROPPED),
        graph_versions_created: load(&GRAPH_VERSIONS_CREATED),
        cas_publications: load(&CAS_PUBLICATIONS),
        cas_retries: load(&CAS_RETRIES),
        batch_sort_calls: load(&BATCH_SORT_CALLS),
        batch_sort_terms: load(&BATCH_SORT_TERMS),
        batch_sort_units: load(&BATCH_SORT_UNITS),
        resource_snapshots_created: load(&RESOURCE_SNAPSHOTS_CREATED),
        resource_arena_locks: load(&RESOURCE_ARENA_LOCKS),
        resource_is_final_calls: load(&RESOURCE_IS_FINAL_CALLS),
        resource_value_calls: load(&RESOURCE_VALUE_CALLS),
        resource_graph_projections: load(&RESOURCE_GRAPH_PROJECTIONS),
        resource_graph_calls: load(&RESOURCE_GRAPH_CALLS),
        resource_graph_value_calls: load(&RESOURCE_GRAPH_VALUE_CALLS),
        resource_edges_calls: load(&RESOURCE_EDGES_CALLS),
        resource_edge_cache_misses: load(&RESOURCE_EDGE_CACHE_MISSES),
        resource_native_edges_enumerated: load(&RESOURCE_NATIVE_EDGES_ENUMERATED),
        resource_nodes_materialized: load(&RESOURCE_NODES_MATERIALIZED),
        resource_descriptors_cloned: load(&RESOURCE_DESCRIPTORS_CLONED),
        resource_nodes_reclaimed: load(&RESOURCE_NODES_RECLAIMED),
        resource_reclaim_nanos: load(&RESOURCE_RECLAIM_NANOS),
        resource_reclaim_max_nanos: load(&RESOURCE_RECLAIM_MAX_NANOS),
    }
}

/// Return an all-zero snapshot when instrumentation is compiled out.
#[cfg(not(feature = "perf-instrumentation"))]
pub fn causal_construction_stats() -> CausalConstructionStats {
    CausalConstructionStats::default()
}

#[cfg(feature = "perf-instrumentation")]
fn counters() -> [&'static AtomicU64; 29] {
    [
        &TERM_INSERT_ATTEMPTS,
        &INPUT_UNITS,
        &VERSION_LOADS,
        &PATH_UNITS_WALKED,
        &EDGE_LISTS_CLONED,
        &EDGE_ARCS_CLONED,
        &NODES_CREATED,
        &NODES_DROPPED,
        &GRAPH_VERSIONS_CREATED,
        &CAS_PUBLICATIONS,
        &CAS_RETRIES,
        &BATCH_SORT_CALLS,
        &BATCH_SORT_TERMS,
        &BATCH_SORT_UNITS,
        &RESOURCE_SNAPSHOTS_CREATED,
        &RESOURCE_ARENA_LOCKS,
        &RESOURCE_IS_FINAL_CALLS,
        &RESOURCE_VALUE_CALLS,
        &RESOURCE_GRAPH_PROJECTIONS,
        &RESOURCE_GRAPH_CALLS,
        &RESOURCE_GRAPH_VALUE_CALLS,
        &RESOURCE_EDGES_CALLS,
        &RESOURCE_EDGE_CACHE_MISSES,
        &RESOURCE_NATIVE_EDGES_ENUMERATED,
        &RESOURCE_NODES_MATERIALIZED,
        &RESOURCE_DESCRIPTORS_CLONED,
        &RESOURCE_NODES_RECLAIMED,
        &RESOURCE_RECLAIM_NANOS,
        &RESOURCE_RECLAIM_MAX_NANOS,
    ]
}