Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use asap_types::ir::schema::{SketchAlgorithm, SketchParams};
pub use asap_types::workload::resources::ModeledCpu;
use serde::{Deserialize, Serialize};

use crate::cost::physical_operator_statistics::{
use crate::cost::operator_statistics::{
EdgeStatistics, OperatorStatistics, PromqlEdgeStatistics, PromqlValueKind,
};

Expand Down Expand Up @@ -303,7 +303,7 @@ fn checked_cpu_product(rows: u64, operations_per_row: u64) -> Result<f64, Analyt
}

fn partitioned_order_estimate(
partitioning: &crate::cost::physical_operator_statistics::PartitionStatistics,
partitioning: &crate::cost::operator_statistics::PartitionStatistics,
comparison_operations: u64,
row_operations: u64,
) -> Result<ResourceEstimate, AnalyticalCostError> {
Expand All @@ -324,7 +324,7 @@ fn partitioned_order_estimate(

fn validate_partitioning(
input: EdgeStatistics,
partitioning: &crate::cost::physical_operator_statistics::PartitionStatistics,
partitioning: &crate::cost::operator_statistics::PartitionStatistics,
partitioned: bool,
) -> Result<(), AnalyticalCostError> {
let inconsistent = |reason| Err(AnalyticalCostError::InconsistentOperatorStatistics(reason));
Expand Down Expand Up @@ -1225,9 +1225,8 @@ pub(crate) fn validate_operator_semantics(
}

fn require_promql_unary(
edges: &crate::cost::physical_operator_statistics::UnaryEdgeStatistics,
) -> Result<crate::cost::physical_operator_statistics::PromqlUnaryEdgeStatistics, AnalyticalCostError>
{
edges: &crate::cost::operator_statistics::UnaryEdgeStatistics,
) -> Result<crate::cost::operator_statistics::PromqlUnaryEdgeStatistics, AnalyticalCostError> {
let promql = edges.promql.ok_or(AnalyticalCostError::MissingOrStale(
"promql_edge_statistics",
))?;
Expand All @@ -1237,11 +1236,8 @@ fn require_promql_unary(
}

fn require_promql_binary(
edges: &crate::cost::physical_operator_statistics::BinaryEdgeStatistics,
) -> Result<
crate::cost::physical_operator_statistics::PromqlBinaryEdgeStatistics,
AnalyticalCostError,
> {
edges: &crate::cost::operator_statistics::BinaryEdgeStatistics,
) -> Result<crate::cost::operator_statistics::PromqlBinaryEdgeStatistics, AnalyticalCostError> {
let promql = edges.promql.ok_or(AnalyticalCostError::MissingOrStale(
"promql_edge_statistics",
))?;
Expand All @@ -1252,7 +1248,7 @@ fn require_promql_binary(
}

fn validate_promql_cardinality_preserving_shape(
promql: crate::cost::physical_operator_statistics::PromqlUnaryEdgeStatistics,
promql: crate::cost::operator_statistics::PromqlUnaryEdgeStatistics,
) -> Result<(), AnalyticalCostError> {
validate_promql_edge(promql.input)?;
validate_promql_edge(promql.output)?;
Expand All @@ -1266,7 +1262,7 @@ fn validate_promql_cardinality_preserving_shape(
}

fn validate_promql_filter_shape(
promql: crate::cost::physical_operator_statistics::PromqlUnaryEdgeStatistics,
promql: crate::cost::operator_statistics::PromqlUnaryEdgeStatistics,
) -> Result<(), AnalyticalCostError> {
validate_promql_edge(promql.input)?;
validate_promql_edge(promql.output)?;
Expand Down Expand Up @@ -1332,7 +1328,7 @@ fn validate_promql_edge_shape(

fn validate_promql_bridge(
operator: PhysicalOperator,
edges: &crate::cost::physical_operator_statistics::UnaryEdgeStatistics,
edges: &crate::cost::operator_statistics::UnaryEdgeStatistics,
) -> Result<(), AnalyticalCostError> {
let promql = require_promql_unary(edges)?;
let valid = match operator {
Expand Down Expand Up @@ -1366,7 +1362,7 @@ fn validate_promql_binary(
cardinality: PromqlVectorCardinality,
build_side: Option<HashJoinBuildSide>,
matching_key_bytes: u64,
edges: &crate::cost::physical_operator_statistics::BinaryEdgeStatistics,
edges: &crate::cost::operator_statistics::BinaryEdgeStatistics,
) -> Result<(), AnalyticalCostError> {
let promql = require_promql_binary(edges)?;
validate_instant_vector_rows(edges.output, promql.output)?;
Expand Down Expand Up @@ -1435,7 +1431,7 @@ fn validate_promql_series_sample(
grouping_key_count: u64,
group_count: u64,
key_bytes: u64,
edges: &crate::cost::physical_operator_statistics::UnaryEdgeStatistics,
edges: &crate::cost::operator_statistics::UnaryEdgeStatistics,
) -> Result<(), AnalyticalCostError> {
let promql = require_promql_unary(edges)?;
validate_instant_vector_rows(edges.output, promql.output)?;
Expand Down Expand Up @@ -1541,7 +1537,7 @@ fn checked_bytes(parts: &[u64]) -> Result<u64, AnalyticalCostError> {
#[cfg(test)]
mod tests {
use super::*;
use crate::cost::physical_operator_statistics::{
use crate::cost::operator_statistics::{
BinaryEdgeStatistics, EdgeStatistics, OperatorStatistics, PartitionStatistics,
PromqlBinaryEdgeStatistics, PromqlEdgeStatistics, PromqlUnaryEdgeStatistics,
PromqlValueKind, UnaryEdgeStatistics,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@
//! (one sketch operation each), still loads: each entry becomes the
//! [`OperatorCost`] of its operator at both phases.
//!
//! [`PlanSelectionSettings::measured_operation_costs`]: super::PlanSelectionSettings::measured_operation_costs
//! [`ResourceUsage`]: super::ResourceUsage
//! [`ResourceSpeed`]: super::ResourceSpeed
//! [`PlanSelectionSettings::measured_operation_costs`]: crate::PlanSelectionSettings::measured_operation_costs
//! [`ResourceUsage`]: crate::ResourceUsage
//! [`ResourceSpeed`]: crate::ResourceSpeed

use std::mem::discriminant;

Expand All @@ -44,15 +44,15 @@ use asap_types::ir::schema::{ExactKind, SketchParams};
use asap_types::ir::{ASAPOp, NonASAPOp, Operator};
use serde::{Deserialize, Serialize};

use crate::cost::analytical_cost::AnalyticalCostError;
use crate::cost::analytical::AnalyticalCostError;

/// The deployment's measured cost table
/// ([`PlanSelectionSettings::measured_operation_costs`]). In JSON, an object
/// with these fields, or (the format of earlier versions) an array of
/// [`MeasuredOperationCost`]. Default: empty, every node priced from the
/// formulas.
///
/// [`PlanSelectionSettings::measured_operation_costs`]: super::PlanSelectionSettings::measured_operation_costs
/// [`PlanSelectionSettings::measured_operation_costs`]: crate::PlanSelectionSettings::measured_operation_costs
#[derive(Debug, Clone, Default, PartialEq, Serialize)]
pub struct MeasuredOperationCosts {
/// One entry per (operator, phase, family) the runtime measured.
Expand Down Expand Up @@ -215,7 +215,7 @@ pub(crate) enum StateFamily<'a> {

/// A node's unit price, from its entry or interpolated between two.
#[derive(Debug, Clone, Copy, PartialEq)]
pub(super) struct UnitPrice {
pub(crate) struct UnitPrice {
pub ns_per_unit: f64,
pub ns_per_invocation: f64,
pub memory_bytes_per_state: Option<f64>,
Expand All @@ -228,7 +228,7 @@ pub(super) struct UnitPrice {
/// two whose sizes (`size_of`: the bytes one state allocates) are nearest
/// below and above the node's are interpolated linearly in log size, and a
/// size outside the measured ones takes the nearest entry's price.
pub(super) fn lookup(
pub(crate) fn lookup(
table: &MeasuredOperationCosts,
operator: OperatorKind,
phase: ExecutionTiming,
Expand Down Expand Up @@ -301,7 +301,7 @@ pub(super) fn lookup(
/// The price of an `Aggregate` at `phase` per input row: the sum over its
/// measures, when each has an entry (one for its own phase winning over
/// one for both).
pub(super) fn aggregate_lookup(
pub(crate) fn aggregate_lookup(
table: &MeasuredOperationCosts,
phase: ExecutionTiming,
measures: &[AggIntent],
Expand Down Expand Up @@ -347,7 +347,7 @@ fn price_of(entry: &OperatorCost) -> UnitPrice {
/// more than one of `sketch`, `exact` and `measure`, two entries for one
/// operator, phase and family, or a non-empty table with `ms_per_cpu_op` 0
/// (a measured time cannot then be counted in operations).
pub(super) fn validate(
pub(crate) fn validate(
table: &MeasuredOperationCosts,
ms_per_cpu_op: f64,
) -> Result<(), AnalyticalCostError> {
Expand Down Expand Up @@ -504,7 +504,7 @@ struct TableFields {
/// node of the candidate's physical plan DAG (`PhysicalASAPDAG`), keyed by
/// its `PhysicalASAPNodeId` in [`CandidateCost::per_node`]; not a machine.
///
/// [`CandidateCost::per_node`]: super::CandidateCost::per_node
/// [`CandidateCost::per_node`]: crate::CandidateCost::per_node
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum NodePriceSource {
Expand Down
12 changes: 8 additions & 4 deletions crates/plan-selection/src/cost/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
//! The analytical resource and cost model plan selection prices with.
//!
//! - [`analytical_cost`] and [`physical_operator_statistics`] — the
//! analytical per-operator resource model.
pub mod analytical_cost;
pub mod physical_operator_statistics;
//! - [`analytical`] and [`operator_statistics`] — the analytical
//! per-operator resource model.
//! - [`measured`] — measured operation costs and their calibration.
//! - [`per_node`] — the memo's per-node local prices.
pub mod analytical;
pub(crate) mod measured;
pub mod operator_statistics;
pub(crate) mod per_node;
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ pub struct PartitionStatistics {
}

/// Workload-dependent evidence for one operator in an already-lowered
/// physical DAG. [`PhysicalOperator`](crate::cost::analytical_cost::PhysicalOperator)
/// physical DAG. [`PhysicalOperator`](crate::cost::analytical::PhysicalOperator)
/// is the authoritative operator vocabulary: every one of its variants has a
/// matching statistics variant here.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
//! query-time scan group priced on its own reads the longest window its
//! parent groups' logical nodes put on it.

#![allow(dead_code)]

use std::collections::{HashMap, HashSet};
use std::rc::Rc;

Expand All @@ -45,8 +47,8 @@ use asap_types::ir::{NonASAPOp, OperatorNode, QueryRoot};
use asap_types::physical::Materialization;
use asap_types::workload::{DataWorkload, QueryWorkloadEntry};

use super::{GroupId, ImplementationCandidate, LocalUsage, Memo};
use crate::cost::physical_operator_statistics::EdgeStatistics;
use crate::cost::operator_statistics::EdgeStatistics;
use crate::search::memo::{GroupId, ImplementationCandidate, LocalUsage, Memo};
use crate::{
accuracy_targets, price_each_node, price_private_nodes, shared_evaluation_rate,
sized_for_failure_probability, CalibrationFit, CostModel, NodeConsumer, PlanningModels,
Expand Down Expand Up @@ -139,7 +141,7 @@ pub(crate) struct PriceCache {
prices: HashMap<PriceKey, Option<(LocalUsage, EdgeStatistics)>>,
/// The raw windows of each scan horizon key of the memo
/// (`coefficients::raw_windows`), computed once per memo.
pub(super) raw_windows: Option<Rc<HashMap<u64, std::collections::BTreeSet<u64>>>>,
pub(crate) raw_windows: Option<Rc<HashMap<u64, std::collections::BTreeSet<u64>>>>,
/// Local prices found in the cache.
pub hits: u64,
/// Local prices computed.
Expand All @@ -156,7 +158,7 @@ impl PriceCache {
}

/// The interned structural node keys.
pub(super) fn keys_mut(&mut self) -> &mut HashMap<String, u32> {
pub(crate) fn keys_mut(&mut self) -> &mut HashMap<String, u32> {
&mut self.keys
}
}
Expand All @@ -170,9 +172,9 @@ struct Part {

/// A child group's sub-DAG's node keys, and its root's.
#[derive(Debug, Default)]
pub(super) struct ChildKeys {
pub(super) nodes: HashSet<u32>,
pub(super) root: Option<u32>,
pub(crate) struct ChildKeys {
pub(crate) nodes: HashSet<u32>,
pub(crate) root: Option<u32>,
}

/// The usage of `candidate`'s private nodes (from its node down to,
Expand Down Expand Up @@ -435,7 +437,7 @@ fn built(

/// The node keys of `child`'s own sub-DAG (one reader, nothing
/// materialized) and its root's key, cached by the child's node.
pub(super) fn child_keys(
pub(crate) fn child_keys(
memo: &Memo,
child: GroupId,
entries: &[QueryWorkloadEntry],
Expand Down Expand Up @@ -478,7 +480,7 @@ pub(super) fn child_keys(
/// producers' keys, and its output schema; placement (timing,
/// materialization) left out, so a child's nodes match whatever is chosen
/// for them.
pub(super) fn keys_of(dag: &PhysicalASAPDAG, interned: &mut HashMap<String, u32>) -> Vec<u32> {
pub(crate) fn keys_of(dag: &PhysicalASAPDAG, interned: &mut HashMap<String, u32>) -> Vec<u32> {
let mut key_of: HashMap<PhysicalASAPNodeId, u32> = HashMap::new();
dag.nodes
.iter()
Expand Down Expand Up @@ -640,7 +642,7 @@ fn price_part(
/// The raw data a query-time scan group priced on its own reads: the
/// longest window its parent groups' nodes put on it (through time
/// shifts); `None` when it is not a scan or no window bounds it.
pub(super) fn scan_lookback_ms(memo: &Memo, group: GroupId) -> Option<u64> {
pub(crate) fn scan_lookback_ms(memo: &Memo, group: GroupId) -> Option<u64> {
let scan = &memo.groups[group.0 as usize];
if !matches!(scan.node.non_asap(), Some(NonASAPOp::Scan { .. })) {
return None;
Expand Down Expand Up @@ -780,7 +782,7 @@ pub(crate) fn frozen_calibration(
#[cfg(test)]
mod tests {
use super::*;
use crate::pass::subexpr::groups::memo_of;
use crate::search::memo::groups::memo_of;
use asap_logical_asap_optimization::per_computation_candidates::generate_per_computation_candidates;
use asap_logical_asap_optimization::test_support::{entry_with, lower_promql};
use asap_types::ir::properties::AccuracyTarget;
Expand Down Expand Up @@ -1143,8 +1145,8 @@ mod tests {
/// every minute: its local price is Stage 3's price of the plan.
#[test]
fn a_pane_chain_at_ingestion_is_priced_as_stage_3_prices_it() {
use crate::pass::subexpr::windows::add_window_composition;
use crate::pass::subexpr::{CandidateOrigin, MemoGroup};
use crate::search::memo::rules::windows::add_window_composition;
use crate::search::memo::{CandidateOrigin, MemoGroup};
use asap_logical_asap_optimization::workload_candidates::stage1_logical_asap_optimization;
use asap_types::ir::schema::schema_support::with_promql_series_identity;
use asap_types::workload::Predictability;
Expand Down
Loading
Loading