mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-09-12 16:32:16 +00:00
test(perf): add monotonic quantile regression controls
Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
This commit is contained in:
@@ -45,7 +45,7 @@ pub(super) struct PromRemoteWriteArgs {
|
||||
value_pattern: ValuePattern,
|
||||
#[arg(long, default_value_t = 0.0)]
|
||||
value_base: f64,
|
||||
#[arg(long, default_value_t = 0.125)]
|
||||
#[arg(long, default_value_t = 0.125, allow_negative_numbers = true)]
|
||||
value_step: f64,
|
||||
#[arg(long, default_value_t = 97)]
|
||||
value_cardinality: u64,
|
||||
@@ -211,8 +211,16 @@ fn splitmix64(mut value: u64) -> u64 {
|
||||
mod tests {
|
||||
use std::collections::HashSet;
|
||||
|
||||
use clap::Parser;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[derive(Parser)]
|
||||
struct Cli {
|
||||
#[command(flatten)]
|
||||
prom_remote_write: PromRemoteWriteArgs,
|
||||
}
|
||||
|
||||
fn args(pattern: ValuePattern) -> PromRemoteWriteArgs {
|
||||
PromRemoteWriteArgs {
|
||||
endpoint: "http://127.0.0.1:4000/v1/prometheus/write".to_string(),
|
||||
@@ -239,6 +247,20 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn value_step_accepts_a_separate_negative_argument() {
|
||||
let cli = Cli::try_parse_from([
|
||||
"query_perf_fixture",
|
||||
"--metric",
|
||||
"fixture_metric",
|
||||
"--value-step",
|
||||
"-1",
|
||||
])
|
||||
.expect("negative value step should parse");
|
||||
|
||||
assert_eq!(cli.prom_remote_write.value_step, -1.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn seeded_random_is_deterministic_in_range_and_highly_distinct() {
|
||||
let mut args = args(ValuePattern::SeededRandom);
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
# PromQL quantile-over-time ascending-value negative control.
|
||||
#
|
||||
# Values are strictly increasing by global sample ordinal. This uses the
|
||||
# Prometheus remote-write/metric-engine ingestion and storage path, whereas
|
||||
# promql_quantile_selection uses direct readable SSTs. Both use 128 series,
|
||||
# 780 samples per series, 15s cadence, and the same evaluation queries.
|
||||
|
||||
[case]
|
||||
name = "promql_quantile_ascending"
|
||||
description = "PromQL quantile_over_time q=0.9 ascending-value remote-write negative control"
|
||||
|
||||
[scenario]
|
||||
kind = "prom_remote_write_then_query"
|
||||
|
||||
[scenario.remote_write]
|
||||
database = "public"
|
||||
metric = "promql_quantile_ascending"
|
||||
series_count = 128
|
||||
samples_per_series = 780
|
||||
sample_chunk_size = 780
|
||||
flush_every_sample_chunks = 1
|
||||
start_unix_millis = 1704067200000
|
||||
step_millis = 15000
|
||||
chunk_series_count = 128
|
||||
|
||||
[scenario.remote_write.value]
|
||||
pattern = "unique"
|
||||
base = 0
|
||||
step = 1
|
||||
|
||||
[scenario.remote_write.prom_store]
|
||||
pending_rows_flush_interval = "1s"
|
||||
max_batch_rows = 100000
|
||||
|
||||
# Selector and response-path control; it does not cover quantile behavior.
|
||||
[[scenario.queries]]
|
||||
name = "plain_selector_control_2h"
|
||||
kind = "tql"
|
||||
query = "TQL ANALYZE VERBOSE (1704070800, 1704078000, '15s') promql_quantile_ascending{host=~'host.*'}"
|
||||
warmup = 3
|
||||
iterations = 9
|
||||
|
||||
[scenario.queries.thresholds]
|
||||
max_candidate_latency_regression_pct = 10
|
||||
|
||||
[[scenario.queries]]
|
||||
name = "quantile_over_time_q90_1m"
|
||||
kind = "tql"
|
||||
query = "TQL ANALYZE VERBOSE (1704070800, 1704078000, '15s') quantile_over_time(0.9, promql_quantile_ascending{host=~'host.*'}[1m])"
|
||||
warmup = 3
|
||||
iterations = 9
|
||||
|
||||
[scenario.queries.thresholds]
|
||||
max_candidate_latency_regression_pct = 10
|
||||
|
||||
[[scenario.queries]]
|
||||
name = "quantile_over_time_q90_5m"
|
||||
kind = "tql"
|
||||
query = "TQL ANALYZE VERBOSE (1704070800, 1704078000, '15s') quantile_over_time(0.9, promql_quantile_ascending{host=~'host.*'}[5m])"
|
||||
warmup = 3
|
||||
iterations = 9
|
||||
|
||||
[scenario.queries.thresholds]
|
||||
max_candidate_latency_regression_pct = 10
|
||||
|
||||
[[scenario.queries]]
|
||||
name = "quantile_over_time_q90_1h"
|
||||
kind = "tql"
|
||||
query = "TQL ANALYZE VERBOSE (1704070800, 1704078000, '15s') quantile_over_time(0.9, promql_quantile_ascending{host=~'host.*'}[1h])"
|
||||
warmup = 3
|
||||
iterations = 9
|
||||
|
||||
[scenario.queries.thresholds]
|
||||
max_candidate_latency_regression_pct = 10
|
||||
|
||||
# host0000 is series ordinal 0. The 1h range at 1704070800 excludes the left
|
||||
# bound, spanning ordinals 1..240; q=0.9 rank 0.9 * (240 - 1) = 215.1 yields 216.1.
|
||||
[[scenario.queries]]
|
||||
name = "quantile_over_time_q90_1h_host0000_eval"
|
||||
kind = "tql"
|
||||
query = "TQL EVAL (1704070800, 1704070800, '15s') quantile_over_time(0.9, promql_quantile_ascending{host='host0000'}[1h])"
|
||||
warmup = 0
|
||||
iterations = 1
|
||||
@@ -0,0 +1,83 @@
|
||||
# PromQL quantile-over-time descending-value negative control.
|
||||
#
|
||||
# Values are strictly decreasing by global sample ordinal. This uses the
|
||||
# Prometheus remote-write/metric-engine ingestion and storage path, whereas
|
||||
# promql_quantile_selection uses direct readable SSTs. Both use 128 series,
|
||||
# 780 samples per series, 15s cadence, and the same evaluation queries.
|
||||
|
||||
[case]
|
||||
name = "promql_quantile_descending"
|
||||
description = "PromQL quantile_over_time q=0.9 descending-value remote-write negative control"
|
||||
|
||||
[scenario]
|
||||
kind = "prom_remote_write_then_query"
|
||||
|
||||
[scenario.remote_write]
|
||||
database = "public"
|
||||
metric = "promql_quantile_descending"
|
||||
series_count = 128
|
||||
samples_per_series = 780
|
||||
sample_chunk_size = 780
|
||||
flush_every_sample_chunks = 1
|
||||
start_unix_millis = 1704067200000
|
||||
step_millis = 15000
|
||||
chunk_series_count = 128
|
||||
|
||||
[scenario.remote_write.value]
|
||||
pattern = "unique"
|
||||
base = 0
|
||||
step = -1
|
||||
|
||||
[scenario.remote_write.prom_store]
|
||||
pending_rows_flush_interval = "1s"
|
||||
max_batch_rows = 100000
|
||||
|
||||
# Selector and response-path control; it does not cover quantile behavior.
|
||||
[[scenario.queries]]
|
||||
name = "plain_selector_control_2h"
|
||||
kind = "tql"
|
||||
query = "TQL ANALYZE VERBOSE (1704070800, 1704078000, '15s') promql_quantile_descending{host=~'host.*'}"
|
||||
warmup = 3
|
||||
iterations = 9
|
||||
|
||||
[scenario.queries.thresholds]
|
||||
max_candidate_latency_regression_pct = 10
|
||||
|
||||
[[scenario.queries]]
|
||||
name = "quantile_over_time_q90_1m"
|
||||
kind = "tql"
|
||||
query = "TQL ANALYZE VERBOSE (1704070800, 1704078000, '15s') quantile_over_time(0.9, promql_quantile_descending{host=~'host.*'}[1m])"
|
||||
warmup = 3
|
||||
iterations = 9
|
||||
|
||||
[scenario.queries.thresholds]
|
||||
max_candidate_latency_regression_pct = 10
|
||||
|
||||
[[scenario.queries]]
|
||||
name = "quantile_over_time_q90_5m"
|
||||
kind = "tql"
|
||||
query = "TQL ANALYZE VERBOSE (1704070800, 1704078000, '15s') quantile_over_time(0.9, promql_quantile_descending{host=~'host.*'}[5m])"
|
||||
warmup = 3
|
||||
iterations = 9
|
||||
|
||||
[scenario.queries.thresholds]
|
||||
max_candidate_latency_regression_pct = 10
|
||||
|
||||
[[scenario.queries]]
|
||||
name = "quantile_over_time_q90_1h"
|
||||
kind = "tql"
|
||||
query = "TQL ANALYZE VERBOSE (1704070800, 1704078000, '15s') quantile_over_time(0.9, promql_quantile_descending{host=~'host.*'}[1h])"
|
||||
warmup = 3
|
||||
iterations = 9
|
||||
|
||||
[scenario.queries.thresholds]
|
||||
max_candidate_latency_regression_pct = 10
|
||||
|
||||
# host0000 is series ordinal 0. At 1704070800, the 1h range is ordinals 1..240;
|
||||
# sorted values are -240..-1, so rank 215.1 interpolates -25 to -24 as -24.9.
|
||||
[[scenario.queries]]
|
||||
name = "quantile_over_time_q90_1h_host0000_eval"
|
||||
kind = "tql"
|
||||
query = "TQL EVAL (1704070800, 1704070800, '15s') quantile_over_time(0.9, promql_quantile_descending{host='host0000'}[1h])"
|
||||
warmup = 0
|
||||
iterations = 1
|
||||
@@ -1,7 +1,7 @@
|
||||
# PromQL quantile-over-time latency regression coverage.
|
||||
#
|
||||
# This is wave-only end-to-end coverage. Ascending- and descending-value
|
||||
# microbenchmark controls remain separately required.
|
||||
# This is wave-only end-to-end coverage. The strictly monotonic remote-write
|
||||
# controls are promql_quantile_ascending and promql_quantile_descending.
|
||||
|
||||
[case]
|
||||
name = "promql_quantile_selection"
|
||||
|
||||
Reference in New Issue
Block a user