diff --git a/.gitignore b/.gitignore index be74354d..3549005b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ Cargo.lock .idea .DS_Store node_modules + +benchmark/target diff --git a/Cargo.toml b/Cargo.toml index 8a24af3d..ff4dbe44 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,4 +64,5 @@ members = [ "async-graphql-warp", "async-graphql-tide", # "async-graphql-lambda", -] + "benchmark", +] diff --git a/README.md b/README.md index a75778ef..0f059100 100644 --- a/README.md +++ b/README.md @@ -54,11 +54,15 @@ To see how you would create a Relay-compliant server using async-graphql, warp, ## Benchmark +Ensure that there is no CPU-heavy process in background! + ```shell script -git clone https://github.com/async-graphql/benchmark -cargo run --release +cd benchmark +cargo bench ``` +Now HTML report is available at `benchmark/target/criterion/report` + ## Features * Fully support async/await diff --git a/benchmark/Cargo.toml b/benchmark/Cargo.toml new file mode 100644 index 00000000..8e138ed0 --- /dev/null +++ b/benchmark/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "graphql-benchmark" +version = "0.1.0" +authors = ["sunli "] +edition = "2018" + +[dev-dependencies] +criterion = "0.3" +simple = { path = "simple" } + +[[bench]] +name = "simple" +harness = false \ No newline at end of file diff --git a/benchmark/benches/simple.rs b/benchmark/benches/simple.rs new file mode 100644 index 00000000..c3a7f6cd --- /dev/null +++ b/benchmark/benches/simple.rs @@ -0,0 +1,12 @@ +use criterion::{criterion_group, criterion_main, Criterion, black_box}; +use simple::{Q, run, parse, serialize, GQLResponse}; + +pub fn criterion_benchmark(c: &mut Criterion) { + c.bench_function("run", |b| b.iter(|| run(black_box(Q)))); + c.bench_function("parse", |b| b.iter(|| parse(black_box(Q)))); + let res = GQLResponse(run(Q)); + c.bench_function("serialize", |b| b.iter(|| serialize(black_box(&res)))); +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); \ No newline at end of file diff --git a/benchmark/simple/Cargo.toml b/benchmark/simple/Cargo.toml new file mode 100644 index 00000000..a8db10a3 --- /dev/null +++ b/benchmark/simple/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "simple" +version = "0.1.0" +authors = ["Ivan Plesskih "] +edition = "2018" + +[dependencies] +async-graphql = { path = "../.." } +async-std = { version = "1.5.0", features = ["attributes"] } +futures = "0.3.4" +serde_json = "*" +lazy_static = "*" +async-graphql-parser = { path = "../../async-graphql-parser" } \ No newline at end of file diff --git a/benchmark/simple/src/lib.rs b/benchmark/simple/src/lib.rs new file mode 100644 index 00000000..fb9ccc4f --- /dev/null +++ b/benchmark/simple/src/lib.rs @@ -0,0 +1,100 @@ +use async_graphql::*; +pub use http::GQLResponse; +use async_graphql_parser::{parse_query, query::Document}; +use async_std::task; + +pub struct QueryRoot; + +#[Object] +impl QueryRoot { + #[field] + async fn value_i32(&self) -> i32 { + 999 + } + + #[field] + async fn obj(&self) -> MyObj { + MyObj + } +} + +pub struct MyObj; + +#[Object] +impl MyObj { + #[field] + async fn value_i32(&self) -> i32 { + 999 + } + + #[field] + async fn value_list(&self) -> &[i32] { + &[1, 2, 3, 4, 5, 6, 7, 8, 9] + } + + #[field] + async fn obj(&self) -> MyObj { + MyObj + } +} + +pub const Q: &str = r#"{ + valueI32 obj { + valueI32 valueList obj { + valueI32 valueList obj { + valueI32 valueList obj { + valueI32 valueList obj { + valueI32 valueList obj { + valueI32 valueList obj { + valueI32 valueList obj { + valueI32 valueList obj { + valueI32 valueList obj { + valueI32 valueList obj { + valueI32 valueList obj { + valueI32 valueList obj { + valueI32 valueList obj { + valueI32 valueList obj { + valueI32 valueList + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } +}"#; + +lazy_static::lazy_static! { + static ref S: Schema = Schema::new(QueryRoot, EmptyMutation, EmptySubscription); + // static ref D: Document = parse_query(Q).unwrap(); +} + +pub fn run(q: &str) -> Result { + task::block_on(async { + S.execute(q).await + }) +} + +pub fn parse(q: &str) -> Document { + parse_query(q).unwrap() +} + +// pub fn validate() { +// check_rules(&S.env.registry, &D, S.validation_mode).unwrap(); +// } +// +// pub fn resolve() { +// do_resolve(...).unwrap(); +// } + +pub fn serialize(r: &GQLResponse) -> String { + serde_json::to_string(&r).unwrap() +}