This is an automated email from the ASF dual-hosted git repository.
jiacai2050 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/horaedb.git
The following commit(s) were added to refs/heads/main by this push:
new 55dcabed feat: add benchmarks for encoding (#1613)
55dcabed is described below
commit 55dcabede31a885d6901b1bc8fab37bcc88fe596
Author: NeoChen <[email protected]>
AuthorDate: Wed Dec 18 02:03:05 2024 -0600
feat: add benchmarks for encoding (#1613)
## Rationale
#1600
## Detailed Changes
Additional benchmarks for this issue
## Test Plan
Append 100 new delta sstfiles to snapshot with 1000 records.
```sh
Benchmarking bench_encoding/new_format_encoding/0: Collecting 10 samples in
estimated 5.0005 s (494k iterations)
bench_encoding/new_format_encoding/0
time: [10.232 µs 10.611 µs 10.900 µs]
change: [-1.5176% +2.1745% +5.9315%] (p = 0.30 >
0.05)
No change in performance detected.
```
---------
Co-authored-by: jiacai2050 <[email protected]>
---
Cargo.lock | 280 +++++++++++++++++++++++++-
Cargo.toml | 7 +-
src/benchmarks/Cargo.toml | 48 +++++
src/benchmarks/README.md | 15 ++
src/benchmarks/benches/bench.rs | 65 ++++++
src/benchmarks/config.toml | 22 ++
src/benchmarks/src/config.rs | 51 +++++
src/benchmarks/src/encoding_bench.rs | 70 +++++++
src/{metric_engine => benchmarks}/src/lib.rs | 20 +-
src/benchmarks/src/util.rs | 170 ++++++++++++++++
src/metric_engine/src/compaction/executor.rs | 1 +
src/metric_engine/src/compaction/scheduler.rs | 1 +
src/metric_engine/src/lib.rs | 4 +-
src/metric_engine/src/manifest/mod.rs | 3 +-
14 files changed, 733 insertions(+), 24 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
index 2c660fc3..add6e153 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -76,6 +76,12 @@ dependencies = [
"libc",
]
+[[package]]
+name = "anes"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
+
[[package]]
name = "anstream"
version = "0.6.18"
@@ -436,6 +442,21 @@ version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
+[[package]]
+name = "benchmarks"
+version = "2.2.0-alpha"
+dependencies = [
+ "bytes",
+ "criterion",
+ "metric_engine",
+ "pb_types",
+ "prost",
+ "serde",
+ "toml",
+ "tracing",
+ "tracing-subscriber",
+]
+
[[package]]
name = "bitflags"
version = "1.3.2"
@@ -545,6 +566,12 @@ dependencies = [
"pkg-config",
]
+[[package]]
+name = "cast"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
+
[[package]]
name = "cc"
version = "1.1.18"
@@ -595,6 +622,58 @@ dependencies = [
"phf_codegen",
]
+[[package]]
+name = "ciborium"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e"
+dependencies = [
+ "ciborium-io",
+ "ciborium-ll",
+ "serde",
+]
+
+[[package]]
+name = "ciborium-io"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
+
+[[package]]
+name = "ciborium-ll"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
+dependencies = [
+ "ciborium-io",
+ "half",
+]
+
+[[package]]
+name = "clap"
+version = "4.5.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84"
+dependencies = [
+ "clap_builder",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.5.23"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838"
+dependencies = [
+ "anstyle",
+ "clap_lex",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
+
[[package]]
name = "colorchoice"
version = "1.0.3"
@@ -662,6 +741,61 @@ dependencies = [
"cfg-if",
]
+[[package]]
+name = "criterion"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f2b12d017a929603d80db1831cd3a24082f8137ce19c69e6447f54f5fc8d692f"
+dependencies = [
+ "anes",
+ "cast",
+ "ciborium",
+ "clap",
+ "criterion-plot",
+ "is-terminal",
+ "itertools 0.10.5",
+ "num-traits",
+ "once_cell",
+ "oorandom",
+ "plotters",
+ "rayon",
+ "regex",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "tinytemplate",
+ "walkdir",
+]
+
+[[package]]
+name = "criterion-plot"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1"
+dependencies = [
+ "cast",
+ "itertools 0.10.5",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
+dependencies = [
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
+dependencies = [
+ "crossbeam-utils",
+]
+
[[package]]
name = "crossbeam-utils"
version = "0.8.20"
@@ -1374,6 +1508,12 @@ version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
+[[package]]
+name = "hermit-abi"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
+
[[package]]
name = "hex"
version = "0.4.3"
@@ -1458,6 +1598,17 @@ version = "3.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8bb03732005da905c88227371639bf1ad885cc712789c011c31c5fb3ab3ccf02"
+[[package]]
+name = "is-terminal"
+version = "0.4.13"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b"
+dependencies = [
+ "hermit-abi 0.4.0",
+ "libc",
+ "windows-sys 0.52.0",
+]
+
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
@@ -1470,6 +1621,15 @@ version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16b73f1c685cfd8ff8d75698ed87e6188cd09944b30c0863d45c2c3699d1da0c"
+[[package]]
+name = "itertools"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
+dependencies = [
+ "either",
+]
+
[[package]]
name = "itertools"
version = "0.13.0"
@@ -1695,7 +1855,7 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec"
dependencies = [
- "hermit-abi",
+ "hermit-abi 0.3.9",
"libc",
"wasi",
"windows-sys 0.52.0",
@@ -1797,7 +1957,7 @@ version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
- "hermit-abi",
+ "hermit-abi 0.3.9",
"libc",
]
@@ -1837,6 +1997,12 @@ version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
+[[package]]
+name = "oorandom"
+version = "11.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9"
+
[[package]]
name = "ordered-float"
version = "2.10.1"
@@ -2026,6 +2192,34 @@ version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec"
+[[package]]
+name = "plotters"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747"
+dependencies = [
+ "num-traits",
+ "plotters-backend",
+ "plotters-svg",
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "plotters-backend"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a"
+
+[[package]]
+name = "plotters-svg"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670"
+dependencies = [
+ "plotters-backend",
+]
+
[[package]]
name = "ppv-lite86"
version = "0.2.20"
@@ -2146,6 +2340,26 @@ dependencies = [
"getrandom",
]
+[[package]]
+name = "rayon"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
+dependencies = [
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
+dependencies = [
+ "crossbeam-deque",
+ "crossbeam-utils",
+]
+
[[package]]
name = "redox_syscall"
version = "0.5.3"
@@ -2298,6 +2512,15 @@ dependencies = [
"serde",
]
+[[package]]
+name = "serde_spanned"
+version = "0.6.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
+dependencies = [
+ "serde",
+]
+
[[package]]
name = "sha2"
version = "0.10.8"
@@ -2548,6 +2771,16 @@ dependencies = [
"crunchy",
]
+[[package]]
+name = "tinytemplate"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
+dependencies = [
+ "serde",
+ "serde_json",
+]
+
[[package]]
name = "tinyvec"
version = "1.8.0"
@@ -2605,6 +2838,40 @@ dependencies = [
"tokio",
]
+[[package]]
+name = "toml"
+version = "0.8.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
+dependencies = [
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_edit",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "toml_edit"
+version = "0.22.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
+dependencies = [
+ "indexmap",
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "winnow",
+]
+
[[package]]
name = "tracing"
version = "0.1.40"
@@ -2969,6 +3236,15 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+[[package]]
+name = "winnow"
+version = "0.6.20"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b"
+dependencies = [
+ "memchr",
+]
+
[[package]]
name = "xz2"
version = "0.1.7"
diff --git a/Cargo.toml b/Cargo.toml
index 4d121b50..d81bca03 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -23,7 +23,7 @@ license = "Apache-2.0"
[workspace]
resolver = "2"
-members = ["src/metric_engine", "src/pb_types", "src/server"]
+members = ["src/benchmarks", "src/metric_engine", "src/pb_types", "src/server"]
[workspace.dependencies]
anyhow = { version = "1.0" }
@@ -50,7 +50,10 @@ tracing = "0.1"
tracing-subscriber = "0.3"
async-scoped = { version = "0.9.0", features = ["use-tokio"] }
test-log = "0.2"
-uuid = { version = "1" }
+uuid = "1"
+criterion = "0.5"
+serde = { version = "1.0", features = ["derive"] }
+toml = "0.8"
# This profile optimizes for good runtime performance.
[profile.release]
diff --git a/src/benchmarks/Cargo.toml b/src/benchmarks/Cargo.toml
new file mode 100644
index 00000000..788c56a3
--- /dev/null
+++ b/src/benchmarks/Cargo.toml
@@ -0,0 +1,48 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+[package]
+name = "benchmarks"
+
+[package.license]
+workspace = true
+
+[package.version]
+workspace = true
+
+[package.authors]
+workspace = true
+
+[package.edition]
+workspace = true
+
+[dependencies]
+bytes = { workspace = true }
+metric_engine = { workspace = true }
+pb_types = { workspace = true }
+prost = { workspace = true }
+serde = { workspace = true }
+toml = { workspace = true }
+tracing = { workspace = true }
+tracing-subscriber = { workspace = true }
+
+[dev-dependencies]
+criterion = { workspace = true }
+
+[[bench]]
+name = "bench"
+harness = false
diff --git a/src/benchmarks/README.md b/src/benchmarks/README.md
new file mode 100644
index 00000000..73cc9d2d
--- /dev/null
+++ b/src/benchmarks/README.md
@@ -0,0 +1,15 @@
+# Benchmarks
+
+A config template can be found in [here](config.toml).
+
+## How to run
+```bash
+ANALYTIC_BENCH_CONFIG_PATH=/path/to/config cargo bench -p benchmarks
+```
+
+Set `RUST_LOG=debug` to enable verbose log.
+
+## Run specific bench:
+```bash
+ANALYTIC_BENCH_CONFIG_PATH=/path/to/config cargo bench --bench bench -p
benchmarks -- bench_encoding
+```
diff --git a/src/benchmarks/benches/bench.rs b/src/benchmarks/benches/bench.rs
new file mode 100644
index 00000000..5ce94444
--- /dev/null
+++ b/src/benchmarks/benches/bench.rs
@@ -0,0 +1,65 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+//! Benchmarks
+
+use std::{cell::RefCell, sync::Once};
+
+use benchmarks::{
+ config::{self, BenchConfig},
+ encoding_bench::EncodingBench,
+};
+use criterion::*;
+
+static INIT_LOG: Once = Once::new();
+
+pub fn init_bench() -> BenchConfig {
+ INIT_LOG.call_once(|| {
+ // install global collector configured based on RUST_LOG env var.
+ tracing_subscriber::fmt::init();
+ });
+
+ config::config_from_env()
+}
+
+fn bench_manifest_encoding(c: &mut Criterion) {
+ let config = init_bench();
+
+ let mut group = c.benchmark_group("manifest_encoding");
+
+ group.measurement_time(config.manifest.bench_measurement_time.0);
+ group.sample_size(config.manifest.bench_sample_size);
+
+ let bench = RefCell::new(EncodingBench::new(config.manifest));
+ group.bench_with_input(
+ BenchmarkId::new("snapshot_encoding", 0),
+ &bench,
+ |b, bench| {
+ let mut bench = bench.borrow_mut();
+ b.iter(|| bench.raw_bytes_bench())
+ },
+ );
+ group.finish();
+}
+
+criterion_group!(
+ name = benches;
+ config = Criterion::default();
+ targets = bench_manifest_encoding,
+);
+
+criterion_main!(benches);
diff --git a/src/benchmarks/config.toml b/src/benchmarks/config.toml
new file mode 100644
index 00000000..1859f303
--- /dev/null
+++ b/src/benchmarks/config.toml
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+[manifest]
+record_count = 1000
+append_count = 100
+bench_measurement_time = "5s"
+bench_sample_size = 10
diff --git a/src/benchmarks/src/config.rs b/src/benchmarks/src/config.rs
new file mode 100644
index 00000000..4da29396
--- /dev/null
+++ b/src/benchmarks/src/config.rs
@@ -0,0 +1,51 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+//! Benchmark configs.
+
+use std::{env, fs};
+
+use serde::Deserialize;
+use tracing::info;
+
+use crate::util::ReadableDuration;
+const BENCH_CONFIG_PATH_KEY: &str = "BENCH_CONFIG_PATH";
+
+#[derive(Debug, Deserialize)]
+pub struct BenchConfig {
+ pub manifest: ManifestConfig,
+}
+
+pub fn config_from_env() -> BenchConfig {
+ let path = env::var(BENCH_CONFIG_PATH_KEY)
+ .expect("Env {BENCH_CONFIG_PATH_KEY} is required to run benches");
+
+ info!(config_path = ?path.as_str(), "Load bench config");
+
+ let toml_str = fs::read_to_string(&path).expect("read bench config file
failed");
+ let config = toml::from_str(&toml_str).expect("parse bench config file
failed");
+ info!(config = ?config, "Bench config");
+ config
+}
+
+#[derive(Deserialize, Debug)]
+pub struct ManifestConfig {
+ pub record_count: usize,
+ pub append_count: usize,
+ pub bench_measurement_time: ReadableDuration,
+ pub bench_sample_size: usize,
+}
diff --git a/src/benchmarks/src/encoding_bench.rs
b/src/benchmarks/src/encoding_bench.rs
new file mode 100644
index 00000000..956925bb
--- /dev/null
+++ b/src/benchmarks/src/encoding_bench.rs
@@ -0,0 +1,70 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+//! encoding bench.
+
+use bytes::Bytes;
+use metric_engine::{
+ manifest::{ManifestUpdate, Snapshot},
+ sst::{FileMeta, SstFile},
+};
+
+use crate::config::ManifestConfig;
+
+pub struct EncodingBench {
+ raw_bytes: Bytes,
+ to_append: Vec<SstFile>,
+}
+
+impl EncodingBench {
+ pub fn new(config: ManifestConfig) -> Self {
+ let sstfile = SstFile::new(
+ 1,
+ FileMeta {
+ max_sequence: 1,
+ num_rows: 1,
+ time_range: (1..2).into(),
+ size: 1,
+ },
+ );
+ let sstfiles = vec![sstfile.clone(); config.record_count];
+ let mut snapshot = Snapshot::try_from(Bytes::new()).unwrap();
+ let update = ManifestUpdate {
+ to_adds: sstfiles,
+ to_deletes: vec![],
+ };
+ let _ = snapshot.merge_update(update);
+
+ EncodingBench {
+ raw_bytes: snapshot.into_bytes().unwrap(),
+ to_append: vec![sstfile; config.append_count],
+ }
+ }
+
+ pub fn raw_bytes_bench(&mut self) {
+ // mock do_merge procedure
+ // first decode snapshot and then append with delta sstfiles,
serialize to bytes
+ // at last
+ let mut snapshot = Snapshot::try_from(self.raw_bytes.clone()).unwrap();
+ let update = ManifestUpdate {
+ to_adds: self.to_append.clone(),
+ to_deletes: vec![],
+ };
+ let _ = snapshot.merge_update(update);
+ let _ = snapshot.into_bytes();
+ }
+}
diff --git a/src/metric_engine/src/lib.rs b/src/benchmarks/src/lib.rs
similarity index 73%
copy from src/metric_engine/src/lib.rs
copy to src/benchmarks/src/lib.rs
index c9e12359..180d1b8a 100644
--- a/src/metric_engine/src/lib.rs
+++ b/src/benchmarks/src/lib.rs
@@ -15,20 +15,8 @@
// specific language governing permissions and limitations
// under the License.
-//! Storage Engine for metrics.
+//! lib for benchmarks.
-#![feature(duration_constructors)]
-mod compaction;
-pub mod error;
-mod macros;
-mod manifest;
-pub mod operator;
-mod read;
-mod sst;
-pub mod storage;
-#[cfg(test)]
-mod test_util;
-pub mod types;
-pub(crate) mod util;
-
-pub use error::{AnyhowError, Error, Result};
+pub mod config;
+pub mod encoding_bench;
+mod util;
diff --git a/src/benchmarks/src/util.rs b/src/benchmarks/src/util.rs
new file mode 100644
index 00000000..623b5b06
--- /dev/null
+++ b/src/benchmarks/src/util.rs
@@ -0,0 +1,170 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+//! Utilities for benchmarks.
+
+use std::{
+ fmt::{self, Write},
+ str::FromStr,
+ time::Duration,
+};
+
+use serde::{
+ de::{self, Visitor},
+ Deserialize, Deserializer, Serialize, Serializer,
+};
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Ord, PartialOrd, Default)]
+pub struct ReadableDuration(pub Duration);
+impl From<Duration> for ReadableDuration {
+ fn from(t: Duration) -> ReadableDuration {
+ ReadableDuration(t)
+ }
+}
+const TIME_MAGNITUDE_1: u64 = 1000;
+const TIME_MAGNITUDE_2: u64 = 60;
+const TIME_MAGNITUDE_3: u64 = 24;
+const UNIT: u64 = 1;
+const MS: u64 = UNIT;
+const SECOND: u64 = MS * TIME_MAGNITUDE_1;
+const MINUTE: u64 = SECOND * TIME_MAGNITUDE_2;
+const HOUR: u64 = MINUTE * TIME_MAGNITUDE_2;
+const DAY: u64 = HOUR * TIME_MAGNITUDE_3;
+
+impl FromStr for ReadableDuration {
+ type Err = String;
+
+ fn from_str(dur_str: &str) -> std::result::Result<ReadableDuration,
String> {
+ let dur_str = dur_str.trim();
+ if !dur_str.is_ascii() {
+ return Err(format!("unexpected ascii string: {dur_str}"));
+ }
+ let err_msg = "valid duration, only d, h, m, s, ms are
supported.".to_owned();
+ let mut left = dur_str.as_bytes();
+ let mut last_unit = DAY + 1;
+ let mut dur = 0f64;
+ while let Some(idx) = left.iter().position(|c| b"dhms".contains(c)) {
+ let (first, second) = left.split_at(idx);
+ let unit = if second.starts_with(b"ms") {
+ left = &left[idx + 2..];
+ MS
+ } else {
+ let u = match second[0] {
+ b'd' => DAY,
+ b'h' => HOUR,
+ b'm' => MINUTE,
+ b's' => SECOND,
+ _ => return Err(err_msg),
+ };
+ left = &left[idx + 1..];
+ u
+ };
+ if unit >= last_unit {
+ return Err("d, h, m, s, ms should occur in given
order.".to_owned());
+ }
+ // do we need to check 12h360m?
+ let number_str = unsafe { std::str::from_utf8_unchecked(first) };
+ dur += match number_str.trim().parse::<f64>() {
+ Ok(n) => n * unit as f64,
+ Err(_) => return Err(err_msg),
+ };
+ last_unit = unit;
+ }
+ if !left.is_empty() {
+ return Err(err_msg);
+ }
+ if dur.is_sign_negative() {
+ return Err("duration should be positive.".to_owned());
+ }
+ let secs = dur as u64 / SECOND;
+ let millis = (dur as u64 % SECOND) as u32 * 1_000_000;
+ Ok(ReadableDuration(Duration::new(secs, millis)))
+ }
+}
+
+impl fmt::Display for ReadableDuration {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let mut dur = self.0.as_millis() as u64;
+ let mut written = false;
+ if dur >= DAY {
+ written = true;
+ write!(f, "{}d", dur / DAY)?;
+ dur %= DAY;
+ }
+ if dur >= HOUR {
+ written = true;
+ write!(f, "{}h", dur / HOUR)?;
+ dur %= HOUR;
+ }
+ if dur >= MINUTE {
+ written = true;
+ write!(f, "{}m", dur / MINUTE)?;
+ dur %= MINUTE;
+ }
+ if dur >= SECOND {
+ written = true;
+ write!(f, "{}s", dur / SECOND)?;
+ dur %= SECOND;
+ }
+ if dur > 0 {
+ written = true;
+ write!(f, "{dur}ms")?;
+ }
+ if !written {
+ write!(f, "0s")?;
+ }
+ Ok(())
+ }
+}
+
+impl Serialize for ReadableDuration {
+ fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok,
S::Error>
+ where
+ S: Serializer,
+ {
+ let mut buffer = String::new();
+ write!(buffer, "{self}").unwrap();
+ serializer.serialize_str(&buffer)
+ }
+}
+
+impl<'de> Deserialize<'de> for ReadableDuration {
+ fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ struct DurVisitor;
+
+ impl Visitor<'_> for DurVisitor {
+ type Value = ReadableDuration;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter<'_>) ->
fmt::Result {
+ formatter.write_str("valid duration")
+ }
+
+ fn visit_str<E>(self, dur_str: &str) ->
std::result::Result<ReadableDuration, E>
+ where
+ E: de::Error,
+ {
+ dur_str.parse().map_err(E::custom)
+ }
+ }
+
+ deserializer.deserialize_str(DurVisitor)
+ }
+}
diff --git a/src/metric_engine/src/compaction/executor.rs
b/src/metric_engine/src/compaction/executor.rs
index c5cf83e2..0e5f9935 100644
--- a/src/metric_engine/src/compaction/executor.rs
+++ b/src/metric_engine/src/compaction/executor.rs
@@ -60,6 +60,7 @@ struct Inner {
}
impl Executor {
+ #[allow(clippy::too_many_arguments)]
pub fn new(
runtime: RuntimeRef,
store: ObjectStoreRef,
diff --git a/src/metric_engine/src/compaction/scheduler.rs
b/src/metric_engine/src/compaction/scheduler.rs
index 4832bf96..3aff52c9 100644
--- a/src/metric_engine/src/compaction/scheduler.rs
+++ b/src/metric_engine/src/compaction/scheduler.rs
@@ -44,6 +44,7 @@ pub struct Scheduler {
}
impl Scheduler {
+ #[allow(clippy::too_many_arguments)]
pub fn new(
runtime: RuntimeRef,
manifest: ManifestRef,
diff --git a/src/metric_engine/src/lib.rs b/src/metric_engine/src/lib.rs
index c9e12359..3c2334de 100644
--- a/src/metric_engine/src/lib.rs
+++ b/src/metric_engine/src/lib.rs
@@ -21,10 +21,10 @@
mod compaction;
pub mod error;
mod macros;
-mod manifest;
+pub mod manifest;
pub mod operator;
mod read;
-mod sst;
+pub mod sst;
pub mod storage;
#[cfg(test)]
mod test_util;
diff --git a/src/metric_engine/src/manifest/mod.rs
b/src/metric_engine/src/manifest/mod.rs
index ffc45567..3489172e 100644
--- a/src/metric_engine/src/manifest/mod.rs
+++ b/src/metric_engine/src/manifest/mod.rs
@@ -27,8 +27,7 @@ use std::{
use anyhow::Context;
use async_scoped::TokioScope;
use bytes::Bytes;
-pub use encoding::ManifestUpdate;
-use encoding::Snapshot;
+pub use encoding::{ManifestUpdate, Snapshot};
use futures::{StreamExt, TryStreamExt};
use object_store::{path::Path, PutPayload};
use prost::Message;
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]