Added new benchmark
This commit is contained in:
parent
c41dba50bc
commit
547c653d28
|
@ -63,6 +63,8 @@ cargo bench
|
||||||
|
|
||||||
Now HTML report is available at `benchmark/target/criterion/report`
|
Now HTML report is available at `benchmark/target/criterion/report`
|
||||||
|
|
||||||
|
Read more here: https://bheisler.github.io/criterion.rs/book/criterion_rs.html
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
* Fully support async/await
|
* Fully support async/await
|
||||||
|
|
|
@ -4,10 +4,22 @@ version = "1.14.11"
|
||||||
authors = ["sunli <scott_s829@163.com>"]
|
authors = ["sunli <scott_s829@163.com>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
async-std = { version = "1.5.0", features = ["attributes"] }
|
||||||
|
futures = "0.3.4"
|
||||||
|
serde_json = "*"
|
||||||
|
async-graphql-parser = { path = "../async-graphql-parser" }
|
||||||
|
async-graphql = { path = ".." }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
criterion = "0.3"
|
criterion = "0.3"
|
||||||
simple = { path = "simple" }
|
simple = { path = "simple" }
|
||||||
|
chat = { path = "chat" }
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
name = "simple"
|
name = "simple"
|
||||||
harness = false
|
harness = false
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "chat"
|
||||||
|
harness = false
|
13
benchmark/benches/chat.rs
Normal file
13
benchmark/benches/chat.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
use chat::{Q, S};
|
||||||
|
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||||
|
use graphql_benchmark::{parse, run, serialize, GQLResponse};
|
||||||
|
|
||||||
|
pub fn bench(c: &mut Criterion) {
|
||||||
|
c.bench_function("chat run", |b| b.iter(|| run(&S, black_box(Q))));
|
||||||
|
c.bench_function("chat parse", |b| b.iter(|| parse(black_box(Q))));
|
||||||
|
let res = GQLResponse(Ok(run(&S, Q)));
|
||||||
|
c.bench_function("chat serialize", |b| b.iter(|| serialize(black_box(&res))));
|
||||||
|
}
|
||||||
|
|
||||||
|
criterion_group!(chat, bench);
|
||||||
|
criterion_main!(chat);
|
|
@ -1,12 +1,15 @@
|
||||||
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||||
use simple::{parse, run, serialize, GQLResponse, Q};
|
use graphql_benchmark::{parse, run, serialize, GQLResponse};
|
||||||
|
use simple::{Q, S};
|
||||||
|
|
||||||
pub fn criterion_benchmark(c: &mut Criterion) {
|
pub fn bench(c: &mut Criterion) {
|
||||||
c.bench_function("run", |b| b.iter(|| run(black_box(Q))));
|
c.bench_function("simple run", |b| b.iter(|| run(&S, black_box(Q))));
|
||||||
c.bench_function("parse", |b| b.iter(|| parse(black_box(Q))));
|
c.bench_function("simple parse", |b| b.iter(|| parse(black_box(Q))));
|
||||||
let res = GQLResponse(run(Q));
|
let res = GQLResponse(Ok(run(&S, Q)));
|
||||||
c.bench_function("serialize", |b| b.iter(|| serialize(black_box(&res))));
|
c.bench_function("simple serialize", |b| {
|
||||||
|
b.iter(|| serialize(black_box(&res)))
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
criterion_group!(benches, criterion_benchmark);
|
criterion_group!(simple, bench);
|
||||||
criterion_main!(benches);
|
criterion_main!(simple);
|
||||||
|
|
9
benchmark/chat/Cargo.toml
Normal file
9
benchmark/chat/Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
[package]
|
||||||
|
name = "chat"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Ivan Plesskih <terma95@gmail.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
async-graphql = { path = "../.." }
|
||||||
|
lazy_static = "*"
|
249
benchmark/chat/src/lib.rs
Normal file
249
benchmark/chat/src/lib.rs
Normal file
|
@ -0,0 +1,249 @@
|
||||||
|
use async_graphql::*;
|
||||||
|
|
||||||
|
pub struct ChatData {
|
||||||
|
pub id: String,
|
||||||
|
pub created_at: String,
|
||||||
|
pub title: String,
|
||||||
|
pub caption: String,
|
||||||
|
pub creator_user_id: String,
|
||||||
|
pub state: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct UserData {
|
||||||
|
pub id: String,
|
||||||
|
pub is_operator: bool,
|
||||||
|
pub phone: u64,
|
||||||
|
pub join_date: String,
|
||||||
|
|
||||||
|
pub state: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ProfileData {
|
||||||
|
pub first_name: String,
|
||||||
|
pub last_name: String,
|
||||||
|
pub city: Option<String>,
|
||||||
|
pub job_title: Option<String>,
|
||||||
|
pub email: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct MessageData {
|
||||||
|
pub id: String,
|
||||||
|
pub user_id: String,
|
||||||
|
pub timestamp: String,
|
||||||
|
pub edited: bool,
|
||||||
|
pub order: i32,
|
||||||
|
pub message: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy_static::lazy_static! {
|
||||||
|
pub static ref CHAT: ChatData = ChatData {
|
||||||
|
id: "1".to_string(),
|
||||||
|
created_at: "today".to_string(),
|
||||||
|
title: "chat".to_string(),
|
||||||
|
caption: "asdasd".to_string(),
|
||||||
|
creator_user_id: "123".to_string(),
|
||||||
|
state: "ACTIVE".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub static ref USER: UserData = UserData {
|
||||||
|
id: "123".to_string(),
|
||||||
|
is_operator: false,
|
||||||
|
phone: 79123273936,
|
||||||
|
join_date: "today".to_string(),
|
||||||
|
state: "ACTIVE".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub static ref PROFILE: ProfileData = ProfileData {
|
||||||
|
first_name: "Ivan".to_string(),
|
||||||
|
last_name: "Plesskih".to_string(),
|
||||||
|
city: Some("Che".to_string()),
|
||||||
|
job_title: Some("progr".to_string()),
|
||||||
|
email: "asd@qwe.ru".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub static ref MESSAGE: MessageData = MessageData {
|
||||||
|
id: "456".to_string(),
|
||||||
|
user_id: "123".to_string(),
|
||||||
|
timestamp: "today".to_string(),
|
||||||
|
edited: false,
|
||||||
|
order: 123,
|
||||||
|
message: "Hello, world!".to_string(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Chat;
|
||||||
|
|
||||||
|
#[Object]
|
||||||
|
impl Chat {
|
||||||
|
pub async fn id(&self) -> ID {
|
||||||
|
ID::from(&CHAT.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn messages(&self) -> Vec<Message> {
|
||||||
|
let mut res = vec![];
|
||||||
|
for _ in 0..30 {
|
||||||
|
res.push(Message);
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn users(&self) -> Vec<User> {
|
||||||
|
let mut res = vec![];
|
||||||
|
for _ in 0..5 {
|
||||||
|
res.push(User);
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn creator(&self) -> User {
|
||||||
|
User
|
||||||
|
}
|
||||||
|
|
||||||
|
#[field(name = "created_at")]
|
||||||
|
pub async fn created_at(&self) -> &String {
|
||||||
|
&CHAT.created_at
|
||||||
|
}
|
||||||
|
pub async fn title(&self) -> &String {
|
||||||
|
&CHAT.title
|
||||||
|
}
|
||||||
|
pub async fn caption(&self) -> &String {
|
||||||
|
&CHAT.caption
|
||||||
|
}
|
||||||
|
pub async fn state(&self) -> &String {
|
||||||
|
&CHAT.state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Message;
|
||||||
|
|
||||||
|
#[Object]
|
||||||
|
impl Message {
|
||||||
|
pub async fn id(&self) -> ID {
|
||||||
|
ID::from(&MESSAGE.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn user(&self) -> User {
|
||||||
|
User
|
||||||
|
}
|
||||||
|
pub async fn timestamp(&self) -> &String {
|
||||||
|
&MESSAGE.timestamp
|
||||||
|
}
|
||||||
|
pub async fn message(&self) -> &String {
|
||||||
|
&MESSAGE.message
|
||||||
|
}
|
||||||
|
pub async fn order(&self) -> i32 {
|
||||||
|
MESSAGE.order
|
||||||
|
}
|
||||||
|
pub async fn edited(&self) -> bool {
|
||||||
|
MESSAGE.edited
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct User;
|
||||||
|
|
||||||
|
#[Object]
|
||||||
|
impl User {
|
||||||
|
pub async fn id(&self) -> ID {
|
||||||
|
ID::from(&USER.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn profile(&self) -> Option<UserProfile> {
|
||||||
|
Some(UserProfile)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[field(name = "is_operator")]
|
||||||
|
pub async fn is_operator(&self) -> bool {
|
||||||
|
USER.is_operator
|
||||||
|
}
|
||||||
|
pub async fn phone(&self) -> String {
|
||||||
|
USER.phone.to_string()
|
||||||
|
}
|
||||||
|
#[field(name = "join_date")]
|
||||||
|
pub async fn join_date(&self) -> &String {
|
||||||
|
&USER.join_date
|
||||||
|
}
|
||||||
|
pub async fn state(&self) -> &String {
|
||||||
|
&USER.state
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct UserProfile;
|
||||||
|
|
||||||
|
#[Object]
|
||||||
|
impl UserProfile {
|
||||||
|
pub async fn email(&self) -> &String {
|
||||||
|
&PROFILE.email
|
||||||
|
}
|
||||||
|
#[field(name = "first_name")]
|
||||||
|
pub async fn first_name(&self) -> &String {
|
||||||
|
&PROFILE.first_name
|
||||||
|
}
|
||||||
|
#[field(name = "last_name")]
|
||||||
|
pub async fn last_name(&self) -> &String {
|
||||||
|
&PROFILE.last_name
|
||||||
|
}
|
||||||
|
#[field(name = "job_title")]
|
||||||
|
pub async fn job_title(&self) -> &Option<String> {
|
||||||
|
&PROFILE.job_title
|
||||||
|
}
|
||||||
|
pub async fn city(&self) -> &Option<String> {
|
||||||
|
&PROFILE.city
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Query;
|
||||||
|
|
||||||
|
#[Object]
|
||||||
|
impl Query {
|
||||||
|
async fn chats(&self) -> Vec<Chat> {
|
||||||
|
let mut res = vec![];
|
||||||
|
for _ in 0..30 {
|
||||||
|
res.push(Chat);
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy_static::lazy_static! {
|
||||||
|
pub static ref S: Schema<Query, EmptyMutation, EmptySubscription> = Schema::new(Query, EmptyMutation, EmptySubscription);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const Q: &str = r#"
|
||||||
|
fragment User on User {
|
||||||
|
id
|
||||||
|
is_operator
|
||||||
|
phone
|
||||||
|
join_date
|
||||||
|
state
|
||||||
|
profile {
|
||||||
|
email
|
||||||
|
first_name
|
||||||
|
last_name
|
||||||
|
job_title
|
||||||
|
city
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
chats {
|
||||||
|
id
|
||||||
|
created_at
|
||||||
|
title
|
||||||
|
caption
|
||||||
|
state
|
||||||
|
creator {
|
||||||
|
...User
|
||||||
|
}
|
||||||
|
messages {
|
||||||
|
id
|
||||||
|
timestamp
|
||||||
|
edited
|
||||||
|
message
|
||||||
|
order
|
||||||
|
}
|
||||||
|
users {
|
||||||
|
...User
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#;
|
|
@ -6,8 +6,4 @@ edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
async-graphql = { path = "../.." }
|
async-graphql = { path = "../.." }
|
||||||
async-std = { version = "1.5.0", features = ["attributes"] }
|
lazy_static = "*"
|
||||||
futures = "0.3.4"
|
|
||||||
serde_json = "*"
|
|
||||||
lazy_static = "*"
|
|
||||||
async-graphql-parser = { path = "../../async-graphql-parser" }
|
|
|
@ -1,7 +1,4 @@
|
||||||
use async_graphql::*;
|
use async_graphql::*;
|
||||||
use async_graphql_parser::{parse_query, query::Document};
|
|
||||||
use async_std::task;
|
|
||||||
pub use http::GQLResponse;
|
|
||||||
|
|
||||||
pub struct QueryRoot;
|
pub struct QueryRoot;
|
||||||
|
|
||||||
|
@ -38,6 +35,11 @@ impl MyObj {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lazy_static::lazy_static! {
|
||||||
|
pub static ref S: Schema<QueryRoot, EmptyMutation, EmptySubscription> = Schema::new(QueryRoot, EmptyMutation, EmptySubscription);
|
||||||
|
// static ref D: Document = parse_query(Q).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
pub const Q: &str = r#"{
|
pub const Q: &str = r#"{
|
||||||
valueI32 obj {
|
valueI32 obj {
|
||||||
valueI32 valueList obj {
|
valueI32 valueList obj {
|
||||||
|
@ -71,28 +73,3 @@ pub const Q: &str = r#"{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}"#;
|
}"#;
|
||||||
|
|
||||||
lazy_static::lazy_static! {
|
|
||||||
static ref S: Schema<QueryRoot, EmptyMutation, EmptySubscription> = Schema::new(QueryRoot, EmptyMutation, EmptySubscription);
|
|
||||||
// static ref D: Document = parse_query(Q).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn run(q: &str) -> Result<QueryResponse> {
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
|
|
32
benchmark/src/lib.rs
Normal file
32
benchmark/src/lib.rs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
pub use async_graphql::http::GQLResponse;
|
||||||
|
use async_graphql::{ObjectType, QueryResponse, Schema, SubscriptionType};
|
||||||
|
use async_graphql_parser::{parse_query, query::Document};
|
||||||
|
use async_std::task;
|
||||||
|
|
||||||
|
pub fn run<Query, Mutation, Subscription>(
|
||||||
|
s: &Schema<Query, Mutation, Subscription>,
|
||||||
|
q: &str,
|
||||||
|
) -> QueryResponse
|
||||||
|
where
|
||||||
|
Query: ObjectType + Send + Sync + 'static,
|
||||||
|
Mutation: ObjectType + Send + Sync + 'static,
|
||||||
|
Subscription: SubscriptionType + Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
task::block_on(async { s.execute(q).await.unwrap() })
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user