use super::{
DiskScratchPolicy, EvaluationIncompleteReason, FormulaPlaneMode, ResourceLedgerSnapshot,
};
use formualizer_common::ResourceExhaustionReason;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum EvaluationResourceClass {
SemanticFormat,
Admission,
RetainedMemory,
ScratchMemory,
WorkTime,
Optimization,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum EvaluationResourceReason {
FormulaPlaneTopologyCandidates,
FormulaPlaneTopologyEdges,
FormulaPlaneTopologyRetainedBytes,
FormulaPlaneMaterializationCells,
FormulaReplayEncodedBytes,
FormulaReplayMemoryBytes,
FormulaReplayDiskBytes,
FormulaReplayFiles,
EvaluationCancelled,
EvaluationError,
}
impl EvaluationResourceClass {
pub const fn as_str(self) -> &'static str {
match self {
Self::SemanticFormat => "semantic_format",
Self::Admission => "admission",
Self::RetainedMemory => "retained_memory",
Self::ScratchMemory => "scratch_memory",
Self::WorkTime => "work_time",
Self::Optimization => "optimization",
}
}
}
impl EvaluationResourceReason {
pub const fn class(self) -> EvaluationResourceClass {
match self {
Self::FormulaPlaneTopologyCandidates | Self::FormulaPlaneTopologyEdges => {
EvaluationResourceClass::Optimization
}
Self::FormulaPlaneTopologyRetainedBytes => EvaluationResourceClass::RetainedMemory,
Self::FormulaPlaneMaterializationCells
| Self::FormulaReplayEncodedBytes
| Self::FormulaReplayDiskBytes
| Self::FormulaReplayFiles => EvaluationResourceClass::Admission,
Self::FormulaReplayMemoryBytes => EvaluationResourceClass::ScratchMemory,
Self::EvaluationCancelled | Self::EvaluationError => EvaluationResourceClass::WorkTime,
}
}
pub const fn as_str(self) -> &'static str {
match self {
Self::FormulaPlaneTopologyCandidates => "formula_plane_topology_candidates",
Self::FormulaPlaneTopologyEdges => "formula_plane_topology_edges",
Self::FormulaPlaneTopologyRetainedBytes => "formula_plane_topology_retained_bytes",
Self::FormulaPlaneMaterializationCells => "formula_plane_materialization_cells",
Self::FormulaReplayEncodedBytes => "formula_replay_encoded_bytes",
Self::FormulaReplayMemoryBytes => "formula_replay_memory_bytes",
Self::FormulaReplayDiskBytes => "formula_replay_disk_bytes",
Self::FormulaReplayFiles => "formula_replay_files",
Self::EvaluationCancelled => "evaluation_cancelled",
Self::EvaluationError => "evaluation_error",
}
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum EvaluationRequestKind {
Vertex,
Targeted,
TargetPreparation,
RecalcPlan,
#[default]
Full,
FullWithDelta,
Cell,
Cells,
CellsCancellable,
CellsWithDelta,
FullCancellable,
TargetedCancellable,
FullLogged,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum EvaluationRequestOutcome {
#[default]
InProgress,
Success,
Cancelled,
Error,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum FormulaPlaneTopologyStrategy {
#[default]
NotUsed,
Legacy,
SkippedNoActiveSpans,
SkippedNoDirtyWork,
Cached,
CompiledAndCached,
ExactPagedIndexed,
ExactInMemoryRuns,
ExactNativeScratch,
ExactRepeatedPasses,
CapacityFallbackMaterialization,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum FormulaPlaneTopologyCacheOutcome {
#[default]
NotUsed,
Hit,
Built,
SkippedOverflow,
SkippedDynamicLegacy,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum FormulaDirtyLeaseOutcome {
#[default]
NotAcquired,
Acquired,
Empty,
Acknowledged,
AcknowledgedPartial,
AcknowledgedEmpty,
RetainedOnCancellation,
RetainedOnError,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum FormulaPlaneRoute {
#[default]
GlobalMixed,
ContractedLegacyIsland,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum FormulaPlaneRoutePhase {
#[default]
Planned,
Executed,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum FormulaPlaneRouteTransitionReason {
#[default]
ProvenIsolated,
DynamicReference,
NamedDependency,
SpillOrArray,
StructuralSummaryUncertain,
UnsupportedReadSummary,
BoundaryDiscoveryOverflow,
SpanCycleDemotion,
RuntimeReplan,
}
pub const FORMULA_PLANE_ROUTE_EVENT_CAPACITY: usize = 16;
pub const FORMULA_PLANE_ROUTE_EVENT_SHEET_CAPACITY: usize = 8;
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub struct FormulaPlaneRouteEvent {
pub island_id: u64,
pub phase: FormulaPlaneRoutePhase,
pub route: FormulaPlaneRoute,
pub sheet_ids: [u16; FORMULA_PLANE_ROUTE_EVENT_SHEET_CAPACITY],
pub sheet_count: u8,
pub authority_epoch: u64,
pub index_epoch: u64,
pub transition_reason: FormulaPlaneRouteTransitionReason,
pub demotion_generation: u32,
pub replan_generation: u32,
}
impl EvaluationRequestKind {
pub const fn as_str(self) -> &'static str {
match self {
Self::Vertex => "vertex",
Self::Targeted => "targeted",
Self::TargetPreparation => "target_preparation",
Self::RecalcPlan => "recalc_plan",
Self::Full => "full",
Self::FullWithDelta => "full_with_delta",
Self::Cell => "cell",
Self::Cells => "cells",
Self::CellsCancellable => "cells_cancellable",
Self::CellsWithDelta => "cells_with_delta",
Self::FullCancellable => "full_cancellable",
Self::TargetedCancellable => "targeted_cancellable",
Self::FullLogged => "full_logged",
}
}
}
impl EvaluationRequestOutcome {
pub const fn as_str(self) -> &'static str {
match self {
Self::InProgress => "in_progress",
Self::Success => "success",
Self::Cancelled => "cancelled",
Self::Error => "error",
}
}
}
impl FormulaPlaneTopologyStrategy {
pub const fn as_str(self) -> &'static str {
match self {
Self::NotUsed => "not_used",
Self::Legacy => "legacy",
Self::SkippedNoActiveSpans => "skipped_no_active_spans",
Self::SkippedNoDirtyWork => "skipped_no_dirty_work",
Self::Cached => "cached",
Self::CompiledAndCached => "compiled_and_cached",
Self::ExactPagedIndexed => "exact_paged_indexed",
Self::ExactInMemoryRuns => "exact_in_memory_runs",
Self::ExactNativeScratch => "exact_native_scratch",
Self::ExactRepeatedPasses => "exact_repeated_passes",
Self::CapacityFallbackMaterialization => "capacity_fallback_materialization",
}
}
pub(crate) const fn severity(self) -> u8 {
match self {
Self::NotUsed => 0,
Self::Legacy => 1,
Self::SkippedNoActiveSpans => 2,
Self::SkippedNoDirtyWork => 3,
Self::Cached => 4,
Self::CompiledAndCached => 5,
Self::ExactPagedIndexed => 6,
Self::ExactInMemoryRuns => 7,
Self::ExactNativeScratch => 8,
Self::ExactRepeatedPasses => 9,
Self::CapacityFallbackMaterialization => 10,
}
}
}
impl FormulaPlaneTopologyCacheOutcome {
pub const fn as_str(self) -> &'static str {
match self {
Self::NotUsed => "not_used",
Self::Hit => "hit",
Self::Built => "built",
Self::SkippedOverflow => "skipped_overflow",
Self::SkippedDynamicLegacy => "skipped_dynamic_legacy",
}
}
pub(crate) const fn severity(self) -> u8 {
match self {
Self::NotUsed => 0,
Self::Hit => 1,
Self::Built => 2,
Self::SkippedOverflow => 3,
Self::SkippedDynamicLegacy => 4,
}
}
}
impl FormulaDirtyLeaseOutcome {
pub const fn as_str(self) -> &'static str {
match self {
Self::NotAcquired => "not_acquired",
Self::Acquired => "acquired",
Self::Empty => "empty",
Self::Acknowledged => "acknowledged",
Self::AcknowledgedPartial => "acknowledged_partial",
Self::AcknowledgedEmpty => "acknowledged_empty",
Self::RetainedOnCancellation => "retained_on_cancellation",
Self::RetainedOnError => "retained_on_error",
}
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
#[non_exhaustive]
pub struct FormulaPlaneTopologyRequestStats {
pub strategy: FormulaPlaneTopologyStrategy,
pub cache_outcome: FormulaPlaneTopologyCacheOutcome,
pub cache_hit_events: u64,
pub cache_build_events: u64,
pub cache_skip_events: u64,
pub cache_skip_streak: u64,
pub exact_pass_count: u64,
pub native_topology_disk_bytes: u64,
pub candidate_cap: Option<u64>,
pub edge_cap: Option<u64>,
pub retained_byte_cap: Option<u64>,
pub operator_guidance: Option<&'static str>,
pub producers_observed: u64,
pub candidates_observed: u64,
pub edges_observed: u64,
pub retained_bytes_observed: u64,
pub candidate_cap_hits: u64,
pub edge_cap_hits: u64,
pub byte_cap_hits: u64,
pub overflow_reason: Option<EvaluationResourceReason>,
pub incomplete_reason: Option<EvaluationIncompleteReason>,
pub route_events: [FormulaPlaneRouteEvent; FORMULA_PLANE_ROUTE_EVENT_CAPACITY],
pub route_event_count: u8,
pub route_events_dropped: u64,
pub route_event_bytes_observed: u64,
pub island_membership_vertices: u64,
pub island_membership_retained_bytes: u64,
pub legacy_relationships_omitted: u64,
pub boundary_relationships_retained: u64,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
#[non_exhaustive]
pub struct EvaluationResourceLedgerRequestStats {
pub retained_limit: Option<u64>,
pub mixed_cache_limit: Option<u64>,
pub retained_current: u64,
pub retained_peak: u64,
pub scratch_limit: Option<u64>,
pub schedule_discovery_limit: Option<u64>,
pub scratch_current: u64,
pub scratch_peak: u64,
pub disk_scratch_policy: Option<DiskScratchPolicy>,
pub work_limit: Option<u64>,
pub work_charged: u64,
pub deadline_ns: Option<u64>,
pub deadline_checkpoints: u64,
pub exhaustion: Option<ResourceExhaustionReason>,
}
impl EvaluationResourceLedgerRequestStats {
pub(crate) fn update(&mut self, snapshot: ResourceLedgerSnapshot) {
self.retained_limit = snapshot.retained_limit;
self.mixed_cache_limit = snapshot.mixed_cache_limit;
self.retained_current = snapshot.retained_current;
self.retained_peak = snapshot.retained_peak;
self.scratch_limit = snapshot.scratch_limit;
self.schedule_discovery_limit = snapshot.schedule_discovery_limit;
self.scratch_current = snapshot.scratch_current;
self.scratch_peak = snapshot.scratch_peak;
self.disk_scratch_policy = snapshot.disk_scratch_policy;
self.work_limit = snapshot.work_limit;
self.work_charged = snapshot.work_charged;
self.deadline_ns = snapshot.deadline_ns;
self.deadline_checkpoints = snapshot.deadline_checkpoints;
self.exhaustion = snapshot.exhaustion;
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
#[non_exhaustive]
pub struct EvaluationRequestPhaseTimings {
pub total_ns: u64,
pub staged_prepare_ns: u64,
pub topology_ns: u64,
pub materialization_ns: u64,
pub evaluation_ns: u64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub struct EvaluationResourceRequestStats {
pub request_id: u64,
pub kind: EvaluationRequestKind,
pub formula_plane_mode: FormulaPlaneMode,
pub outcome: EvaluationRequestOutcome,
pub staged_selected: u64,
pub staged_retained: u64,
pub target_requested: u64,
pub target_normalized_regions: u64,
pub target_scope_level: u8,
pub target_widening_reason_bits: u64,
pub graph_source_scratch_estimated: u64,
pub graph_source_scratch_observed: u64,
pub target_commit_estimated_work: u64,
pub target_commit_actual_work: u64,
pub target_commit_window_ns: u64,
pub target_admission_failure: Option<ResourceExhaustionReason>,
pub evaluation_commit_preflight_count: u64,
pub evaluation_commit_estimated_ns: u64,
pub evaluation_commit_actual_ns: u64,
pub runtime_replan_rounds: u64,
pub runtime_widening_rounds: u64,
pub workbook_exact_attempts: u64,
pub topology: FormulaPlaneTopologyRequestStats,
pub fallback_materialized_cells: u64,
pub cycle_materialized_cells: u64,
pub dirty_lease: FormulaDirtyLeaseOutcome,
pub ledger: EvaluationResourceLedgerRequestStats,
pub phases: EvaluationRequestPhaseTimings,
}
impl EvaluationResourceRequestStats {
pub(crate) fn new(
request_id: u64,
kind: EvaluationRequestKind,
formula_plane_mode: FormulaPlaneMode,
staged_retained: usize,
) -> Self {
Self {
request_id,
kind,
formula_plane_mode,
outcome: EvaluationRequestOutcome::InProgress,
staged_selected: 0,
staged_retained: staged_retained as u64,
target_requested: 0,
target_normalized_regions: 0,
target_scope_level: 0,
target_widening_reason_bits: 0,
graph_source_scratch_estimated: 0,
graph_source_scratch_observed: 0,
target_commit_estimated_work: 0,
target_commit_actual_work: 0,
target_commit_window_ns: 0,
target_admission_failure: None,
evaluation_commit_preflight_count: 0,
evaluation_commit_estimated_ns: 0,
evaluation_commit_actual_ns: 0,
runtime_replan_rounds: 0,
runtime_widening_rounds: 0,
workbook_exact_attempts: 0,
topology: FormulaPlaneTopologyRequestStats {
strategy: if formula_plane_mode == FormulaPlaneMode::AuthoritativeExperimental {
FormulaPlaneTopologyStrategy::NotUsed
} else {
FormulaPlaneTopologyStrategy::Legacy
},
..FormulaPlaneTopologyRequestStats::default()
},
fallback_materialized_cells: 0,
cycle_materialized_cells: 0,
dirty_lease: FormulaDirtyLeaseOutcome::NotAcquired,
ledger: EvaluationResourceLedgerRequestStats::default(),
phases: EvaluationRequestPhaseTimings::default(),
}
}
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
#[non_exhaustive]
pub struct EvaluationResourceBaselineStats {
pub last_request_id: u64,
pub requests_started: u64,
pub requests_succeeded: u64,
pub requests_cancelled: u64,
pub requests_errored: u64,
pub staged_selected_total: u64,
pub topology_cache_hits: u64,
pub topology_cache_builds: u64,
pub topology_cache_skips: u64,
pub topology_cache_skip_streak_current: u64,
pub topology_cache_skip_streak_max: u64,
pub topology_exact_passes_total: u64,
pub topology_native_disk_bytes_total: u64,
pub topology_candidate_cap_hits: u64,
pub topology_edge_cap_hits: u64,
pub topology_byte_cap_hits: u64,
pub topology_candidates_observed_total: u64,
pub topology_edges_observed_total: u64,
pub topology_retained_bytes_observed_max: u64,
pub fallback_materialized_cells_total: u64,
pub cycle_materialized_cells_total: u64,
pub dirty_leases_acknowledged: u64,
pub dirty_leases_retained_on_cancel: u64,
pub dirty_leases_retained_on_error: u64,
pub ledger_retained_peak: u64,
pub ledger_scratch_peak: u64,
pub ledger_work_charged_total: u64,
pub ledger_deadline_checkpoints: u64,
pub ledger_exhaustions: u64,
pub last_ledger_exhaustion: Option<ResourceExhaustionReason>,
pub total_request_ns: u64,
pub staged_prepare_ns: u64,
pub topology_ns: u64,
pub materialization_ns: u64,
pub evaluation_ns: u64,
}
impl EvaluationResourceBaselineStats {
pub(crate) fn record_started(&mut self, request_id: u64) {
self.last_request_id = request_id;
self.requests_started = self.requests_started.saturating_add(1);
}
pub(crate) fn record_finished(&mut self, stats: &EvaluationResourceRequestStats) {
match stats.outcome {
EvaluationRequestOutcome::Success => {
self.requests_succeeded = self.requests_succeeded.saturating_add(1)
}
EvaluationRequestOutcome::Cancelled => {
self.requests_cancelled = self.requests_cancelled.saturating_add(1)
}
EvaluationRequestOutcome::Error => {
self.requests_errored = self.requests_errored.saturating_add(1)
}
EvaluationRequestOutcome::InProgress => {}
}
self.staged_selected_total = self
.staged_selected_total
.saturating_add(stats.staged_selected);
self.topology_cache_hits = self
.topology_cache_hits
.saturating_add(stats.topology.cache_hit_events);
self.topology_cache_builds = self
.topology_cache_builds
.saturating_add(stats.topology.cache_build_events);
self.topology_cache_skips = self
.topology_cache_skips
.saturating_add(stats.topology.cache_skip_events);
self.topology_cache_skip_streak_current = stats.topology.cache_skip_streak;
self.topology_cache_skip_streak_max = self
.topology_cache_skip_streak_max
.max(stats.topology.cache_skip_streak);
self.topology_exact_passes_total = self
.topology_exact_passes_total
.saturating_add(stats.topology.exact_pass_count);
self.topology_native_disk_bytes_total = self
.topology_native_disk_bytes_total
.saturating_add(stats.topology.native_topology_disk_bytes);
self.topology_candidate_cap_hits = self
.topology_candidate_cap_hits
.saturating_add(stats.topology.candidate_cap_hits);
self.topology_edge_cap_hits = self
.topology_edge_cap_hits
.saturating_add(stats.topology.edge_cap_hits);
self.topology_byte_cap_hits = self
.topology_byte_cap_hits
.saturating_add(stats.topology.byte_cap_hits);
self.topology_candidates_observed_total = self
.topology_candidates_observed_total
.saturating_add(stats.topology.candidates_observed);
self.topology_edges_observed_total = self
.topology_edges_observed_total
.saturating_add(stats.topology.edges_observed);
self.topology_retained_bytes_observed_max = self
.topology_retained_bytes_observed_max
.max(stats.topology.retained_bytes_observed);
self.fallback_materialized_cells_total = self
.fallback_materialized_cells_total
.saturating_add(stats.fallback_materialized_cells);
self.cycle_materialized_cells_total = self
.cycle_materialized_cells_total
.saturating_add(stats.cycle_materialized_cells);
match stats.dirty_lease {
FormulaDirtyLeaseOutcome::Acknowledged
| FormulaDirtyLeaseOutcome::AcknowledgedPartial
| FormulaDirtyLeaseOutcome::AcknowledgedEmpty => {
self.dirty_leases_acknowledged = self.dirty_leases_acknowledged.saturating_add(1)
}
FormulaDirtyLeaseOutcome::RetainedOnCancellation => {
self.dirty_leases_retained_on_cancel =
self.dirty_leases_retained_on_cancel.saturating_add(1)
}
FormulaDirtyLeaseOutcome::RetainedOnError => {
self.dirty_leases_retained_on_error =
self.dirty_leases_retained_on_error.saturating_add(1)
}
_ => {}
}
self.ledger_retained_peak = self.ledger_retained_peak.max(stats.ledger.retained_peak);
self.ledger_scratch_peak = self.ledger_scratch_peak.max(stats.ledger.scratch_peak);
self.ledger_work_charged_total = self
.ledger_work_charged_total
.saturating_add(stats.ledger.work_charged);
self.ledger_deadline_checkpoints = self
.ledger_deadline_checkpoints
.saturating_add(stats.ledger.deadline_checkpoints);
if let Some(reason) = stats.ledger.exhaustion {
self.ledger_exhaustions = self.ledger_exhaustions.saturating_add(1);
self.last_ledger_exhaustion = Some(reason);
}
self.total_request_ns = self.total_request_ns.saturating_add(stats.phases.total_ns);
self.staged_prepare_ns = self
.staged_prepare_ns
.saturating_add(stats.phases.staged_prepare_ns);
self.topology_ns = self.topology_ns.saturating_add(stats.phases.topology_ns);
self.materialization_ns = self
.materialization_ns
.saturating_add(stats.phases.materialization_ns);
self.evaluation_ns = self
.evaluation_ns
.saturating_add(stats.phases.evaluation_ns);
}
}