mirror of
https://github.com/GreptimeTeam/greptimedb.git
synced 2026-09-06 13:38:59 +00:00
* fix(perf): align direct-SST CREATE TABLE with baked index metadata
The offline fixture generator (query_perf_fixture::direct_sst::
build_region_metadata) bakes greptime:inverted_index /
greptime:skipping_index field metadata into the region manifest for
tag/field columns, but create_table_sql emitted a bare CREATE TABLE
without those declarations. MergeScan's remote-schema validation then
failed on any tag/field projection (HTTP 500 'advertised remote stream
schema field mismatch'), breaking direct_readable_sst perf cases.
CREATE TABLE now declares the matching SKIPPING INDEX WITH
(granularity='1') / INVERTED INDEX column options. A round-trip test
proves the emitted SQL is parser-valid and yields the exact catalog
metadata.
Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
* perf(servers): speed up Prometheus JSON response building with ryu and per-series entry reuse
PrometheusJsonResponse::record_batches_to_data spends ~47% of its CPU
in f64::to_string() per sample and ~32% in IndexMap::entry() per row
(60s profile of concurrent query_range workloads, ~800k series).
- Replace f64::to_string() with ryu::Buffer::format_finite for finite
values (shortest round-trip, 3-5x faster); NaN/+Inf/-Inf keep the
previous std formatting so wire output is unchanged.
- Remember the previous row's label vector and entry index; query output
is clustered by series, so consecutive rows reuse the same IndexMap
entry via get_index_mut instead of rebuilding and hashing the label
vector (worst case adds one Vec comparison per series transition).
Also adds a query-regression case (prom_json_response) that measures the
real Prometheus HTTP range API path (/v1/prometheus/api/v1/query_range),
which is the only frontend path that builds the Prometheus JSON response
(TQL ANALYZE formats the SQL JSON shape instead), plus a prom_http query
kind in the regression runner.
Perf (aligned base d90cca4b75, 256 series x 481 points):
- prom_range_2h (JSON response path): 29.31ms -> 21.46ms (-26.8%)
- tql_range_2h_control (non-JSON path): +1.87% (noise)
Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
* fix(servers): keep Prometheus wire format for integral floats with ryu
ryu::Buffer::format_finite prints integral values as "1.0", but the
Prometheus JSON wire format (matching std f64::to_string) expects "1".
Strip the trailing ".0" that ryu only emits for integral values; extreme
values keep ryu scientific notation, and NaN/Inf keep std output. Adds
wire-format tests covering 1.0, 0.0, -0.0, 1.5, 0.1, 1e21, 1e30, 1e-7,
f64::MAX, NaN, ±Inf.
Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
* fix(servers): address Prometheus response review feedback
Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
* perf(servers)!: use ryu for Prometheus sample values
Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
* fix(cmd): skip Prometheus execution time extraction
Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
---------
Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
90 lines
2.5 KiB
TOML
90 lines
2.5 KiB
TOML
# Prometheus JSON response building benchmark (issue #8805).
|
|
#
|
|
# Exercises the serial per-request
|
|
# `PrometheusJsonResponse::record_batches_to_data`
|
|
# (src/servers/src/http/result/prometheus_resp.rs) path, ryu float formatting,
|
|
# and its per-series IndexMap entry reuse.
|
|
#
|
|
# 256 series x 481 evaluation timestamps (2h at 15s) = ~123k output samples
|
|
# per request. The primary `prom_http` query builds the Prometheus JSON
|
|
# response. The TQL ANALYZE control runs the same workload without building the
|
|
# Prometheus JSON response, to measure query-engine/scan variance.
|
|
|
|
[case]
|
|
name = "prom_json_response"
|
|
description = "Prometheus HTTP API JSON response building for large range queries"
|
|
|
|
[scenario]
|
|
kind = "direct_readable_sst"
|
|
seed = 8805
|
|
|
|
[[scenario.tables]]
|
|
database = "public"
|
|
name = "prom_json_response"
|
|
engine = "mito"
|
|
append_mode = true
|
|
sst_format = "flat"
|
|
primary_key = ["host", "instance"]
|
|
time_index = "ts"
|
|
|
|
[[scenario.tables.columns]]
|
|
name = "host"
|
|
type = "STRING"
|
|
semantic = "tag"
|
|
distribution = { kind = "cardinality", values = 16, prefix = "host" }
|
|
|
|
[[scenario.tables.columns]]
|
|
name = "instance"
|
|
type = "STRING"
|
|
semantic = "tag"
|
|
distribution = { kind = "cardinality", values = 256, prefix = "instance" }
|
|
|
|
[[scenario.tables.columns]]
|
|
name = "value"
|
|
type = "DOUBLE"
|
|
semantic = "field"
|
|
distribution = { kind = "deterministic_wave", min = 0.0, max = 1000.0 }
|
|
|
|
[[scenario.tables.columns]]
|
|
name = "ts"
|
|
type = "TIMESTAMP(9)"
|
|
semantic = "timestamp"
|
|
|
|
[scenario.layout]
|
|
regions = 1
|
|
sst_count = 16
|
|
rows_per_sst = 7680
|
|
row_group_size = 1920
|
|
series_count = 256
|
|
start_unix_nanos = 1704067200000000000
|
|
step_nanos = 15000000000
|
|
time_range_layout = "non_overlapping_per_sst"
|
|
series_layout = "timestamp_major"
|
|
|
|
# Primary case: Prometheus HTTP range query over the full 2h window.
|
|
# 256 series x 481 points -> ~123k samples built and serialized per request.
|
|
[[scenario.queries]]
|
|
name = "prom_range_2h"
|
|
kind = "prom_http"
|
|
query = "prom_json_response{host=~\"host.*\"}"
|
|
start = "1704067200"
|
|
end = "1704074400"
|
|
step = "15s"
|
|
warmup = 3
|
|
iterations = 9
|
|
|
|
[scenario.queries.thresholds]
|
|
max_candidate_latency_regression_pct = 10
|
|
|
|
# Control: same workload through the SQL/TQL frontend path, which does not
|
|
# build the Prometheus JSON response. Isolates query-engine/scan variance.
|
|
[[scenario.queries]]
|
|
name = "tql_range_2h_control"
|
|
kind = "tql"
|
|
query = "TQL ANALYZE VERBOSE (1704067200, 1704074400, '15s') prom_json_response{host=~'host.*'}"
|
|
warmup = 3
|
|
iterations = 9
|
|
|
|
[scenario.queries.thresholds]
|
|
max_candidate_latency_regression_pct = 10
|