Testing - Add microbenchmarks for query parsing and execution. ()

This commit is contained in:
Finn Bear 2023-05-01 10:15:42 -07:00 committed by GitHub
parent a76910e826
commit 46c5b4d7f1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 359 additions and 2 deletions

44
.github/workflows/bench.yml vendored Normal file
View file

@ -0,0 +1,44 @@
name: Benchmark
on: [pull_request]
defaults:
run:
shell: bash
jobs:
bench:
name: Bench library
runs-on: ubuntu-20.04-16-cores
steps:
- name: Install stable toolchain
uses: dtolnay/rust-toolchain@stable
- name: Install dependencies
run: |
sudo apt-get -qq -y update
sudo apt-get -qq -y install protobuf-compiler libprotobuf-dev
cargo install --quiet critcmp
- name: Checkout baseline
uses: actions/checkout@v3
with:
ref: ${{ github.base_ref }}
- name: Benchmark baseline
run: cargo bench --quiet --package surrealdb --no-default-features --features kv-mem -- --save-baseline baseline
- name: Checkout changes
uses: actions/checkout@v3
- name: Benchmark changes
run: cargo bench --quiet --package surrealdb --no-default-features --features kv-mem -- --save-baseline changes
- name: Compare results
run: critcmp baseline changes | tee benchmark_results
- name: Save results as artifact
uses: actions/upload-artifact@v1
with:
name: Benchmark Results
path: benchmark_results

175
Cargo.lock generated
View file

@ -264,6 +264,12 @@ dependencies = [
"libc",
]
[[package]]
name = "anes"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
[[package]]
name = "any_ascii"
version = "0.3.2"
@ -742,6 +748,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.0.79"
@ -791,6 +803,33 @@ dependencies = [
"winapi",
]
[[package]]
name = "ciborium"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0c137568cc60b904a7724001b35ce2630fd00d5d84805fbb608ab89509d788f"
dependencies = [
"ciborium-io",
"ciborium-ll",
"serde",
]
[[package]]
name = "ciborium-io"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "346de753af073cc87b52b2083a506b38ac176a44cfb05497b622e27be899b369"
[[package]]
name = "ciborium-ll"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "213030a2b5a4e0c0892b6652260cf6ccac84827b83a85a534e178e3906c4cf1b"
dependencies = [
"ciborium-io",
"half",
]
[[package]]
name = "cipher"
version = "0.4.4"
@ -947,6 +986,42 @@ dependencies = [
"cfg-if",
]
[[package]]
name = "criterion"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb"
dependencies = [
"anes",
"atty",
"cast",
"ciborium",
"clap",
"criterion-plot",
"itertools 0.10.5",
"lazy_static",
"num-traits",
"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 = "critical-section"
version = "1.1.1"
@ -963,6 +1038,30 @@ dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
dependencies = [
"cfg-if",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.15"
@ -2251,6 +2350,15 @@ version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memoffset"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
dependencies = [
"autocfg",
]
[[package]]
name = "mime"
version = "0.3.17"
@ -2448,6 +2556,12 @@ version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]]
name = "oorandom"
version = "11.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
[[package]]
name = "openssl"
version = "0.10.50"
@ -2766,6 +2880,34 @@ version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
[[package]]
name = "plotters"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97"
dependencies = [
"num-traits",
"plotters-backend",
"plotters-svg",
"wasm-bindgen",
"web-sys",
]
[[package]]
name = "plotters-backend"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142"
[[package]]
name = "plotters-svg"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f"
dependencies = [
"plotters-backend",
]
[[package]]
name = "ppv-lite86"
version = "0.2.17"
@ -3093,6 +3235,28 @@ dependencies = [
"rand_core 0.6.4",
]
[[package]]
name = "rayon"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
"num_cpus",
]
[[package]]
name = "redox_syscall"
version = "0.2.16"
@ -3793,6 +3957,7 @@ dependencies = [
"bigdecimal",
"bung",
"chrono",
"criterion",
"dmp",
"echodb",
"env_logger 0.10.0",
@ -4086,6 +4251,16 @@ dependencies = [
"time-core",
]
[[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.6.0"

View file

@ -102,6 +102,7 @@ ulid = { version = "1.0.0", features = ["serde"] }
url = "2.3.1"
[dev-dependencies]
criterion = "0.4"
env_logger = "0.10.0"
temp-dir = "0.1.11"
time = { version = "0.3.20", features = ["serde"] }
@ -116,9 +117,17 @@ wasm-bindgen-futures = "0.4.34"
ws_stream_wasm = "0.7.4"
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
tokio = { version = "1.27.0", default-features = false, features = ["macros", "io-util", "io-std", "fs", "rt-multi-thread"] }
tokio = { version = "1.27.0", default-features = false, features = ["macros", "io-util", "io-std", "fs", "rt-multi-thread", "time"] }
tokio-tungstenite = { version = "0.18.0", optional = true }
uuid = { version = "1.3.1", features = ["serde", "v4", "v7"] }
[lib]
bench = false
bench = false
[[bench]]
name = "executor"
harness = false
[[bench]]
name = "parser"
harness = false

12
lib/benches/README.md Normal file
View file

@ -0,0 +1,12 @@
# Benchmarks
This directory contains some micro-benchmarks that can help objectively
establish the performance implications of a change.
## Manual usage
Execute the following command at the top level of the repository:
```console
cargo bench --package surrealdb --no-default-features --features kv-mem
```

52
lib/benches/executor.rs Normal file
View file

@ -0,0 +1,52 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput};
use surrealdb::{dbs::Session, kvs::Datastore};
macro_rules! query {
($c: expr, $name: ident, $query: expr) => {
query!($c, $name, "", $query);
};
($c: expr, $name: ident, $setup: expr, $query: expr) => {
$c.bench_function(stringify!($name), |b| {
let (dbs, ses) = futures::executor::block_on(async {
let dbs = Datastore::new("memory").await.unwrap();
let ses = Session::for_kv().with_ns("test").with_db("test");
let setup = $setup;
if !setup.is_empty() {
dbs.execute(setup, &ses, None, false).await.unwrap();
}
(dbs, ses)
});
b.iter(|| {
futures::executor::block_on(async {
black_box(dbs.execute(black_box($query), &ses, None, false).await).unwrap();
});
})
});
};
}
fn bench_executor(c: &mut Criterion) {
let mut c = c.benchmark_group("executor");
c.throughput(Throughput::Elements(1));
query!(c, create_delete_simple, "CREATE person:one; DELETE person:one;");
query!(c, select_simple_one, "CREATE person:tobie;", "SELECT * FROM person;");
query!(c, select_simple_five, "CREATE person:one; CREATE person:two; CREATE person:three; CREATE person:four; CREATE person:five;", "SELECT * FROM person;");
query!(c, select_future, "SELECT * FROM <future>{5};");
query!(
c,
update_simple,
"CREATE thing:one SET value = 0;",
"UPDATE thing SET value = value + 1;"
);
query!(
c,
select_record_link,
"CREATE person:one SET friend = person:two; CREATE person:two SET age = 30;",
"SELECT * FROM person:one.friend.age;"
);
c.finish();
}
criterion_group!(benches, bench_executor);
criterion_main!(benches);

65
lib/benches/parser.rs Normal file
View file

@ -0,0 +1,65 @@
use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput};
macro_rules! parser {
($c: expr, $name: ident, $parser: path, $text: expr) => {
$c.bench_function(stringify!($name), |b| {
let text = $text;
b.iter(|| black_box($parser(black_box(text))).unwrap())
});
};
}
fn bench_parser(c: &mut Criterion) {
let mut c = c.benchmark_group("parser");
c.throughput(Throughput::Elements(1));
parser!(c, select_simple, surrealdb::sql::parse, "SELECT * FROM person;");
parser!(
c,
select_complex,
surrealdb::sql::parse,
"SELECT name, age, country FROM person WHERE hair = 'brown' AND is_vegetarian;"
);
parser!(c, transaction, surrealdb::sql::parse, "BEGIN TRANSACTION; UPDATE person:finn SET squirrels = 'yes'; SELECT * FROM person; COMMIT TRANSACTION;");
parser!(c, datetime, surrealdb::sql::parse, "RETURN '2022-07-03T07:18:52.841147+02:00';");
parser!(c, duration, surrealdb::sql::parse, "RETURN [100w, 5d, 20m, 2s];");
parser!(
c,
casting_deep,
surrealdb::sql::parse,
"RETURN <float><float><float><float><float>1.0;"
);
parser!(
c,
json_geo,
surrealdb::sql::parse,
"RETURN { type: 'Point', coordinates: [-0.118092, 51.509865] };"
);
parser!(c, json_number, surrealdb::sql::json, "1.2345");
parser!(
c,
json_small_object,
surrealdb::sql::json,
"{'key': true, 'number': 42.0, 'value': null}"
);
parser!(c, json_small_array, surrealdb::sql::json, "[1, false, null, 'foo']");
parser!(
c,
json_large_array,
surrealdb::sql::json,
&format!("[{}]", (1..=100).map(|n| n.to_string()).collect::<Vec<_>>().join(", "))
);
parser!(
c,
json_large_object,
surrealdb::sql::json,
&format!(
"{{{}}}",
&(1..=100).map(|n| format!("'{n}': {n}")).collect::<Vec<_>>().join(", ")
)
);
c.finish();
}
criterion_group!(benches, bench_parser);
criterion_main!(benches);