commit
4fcd5ca167
|
@ -63,6 +63,8 @@ cargo bench
|
|||
|
||||
Now HTML report is available at `benchmark/target/criterion/report`
|
||||
|
||||
Read more here: https://bheisler.github.io/criterion.rs/book/criterion_rs.html
|
||||
|
||||
## Features
|
||||
|
||||
* Fully support async/await
|
||||
|
|
|
@ -4,10 +4,22 @@ version = "1.14.11"
|
|||
authors = ["sunli <scott_s829@163.com>"]
|
||||
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]
|
||||
criterion = "0.3"
|
||||
simple = { path = "simple" }
|
||||
chat = { path = "chat" }
|
||||
|
||||
[[bench]]
|
||||
name = "simple"
|
||||
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 simple::{parse, run, serialize, GQLResponse, Q};
|
||||
use graphql_benchmark::{parse, run, serialize, GQLResponse};
|
||||
use simple::{Q, S};
|
||||
|
||||
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))));
|
||||
pub fn bench(c: &mut Criterion) {
|
||||
c.bench_function("simple run", |b| b.iter(|| run(&S, black_box(Q))));
|
||||
c.bench_function("simple parse", |b| b.iter(|| parse(black_box(Q))));
|
||||
let res = GQLResponse(Ok(run(&S, Q)));
|
||||
c.bench_function("simple serialize", |b| {
|
||||
b.iter(|| serialize(black_box(&res)))
|
||||
});
|
||||
}
|
||||
|
||||
criterion_group!(benches, criterion_benchmark);
|
||||
criterion_main!(benches);
|
||||
criterion_group!(simple, bench);
|
||||
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]
|
||||
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" }
|
||||
lazy_static = "*"
|
|
@ -1,7 +1,4 @@
|
|||
use async_graphql::*;
|
||||
use async_graphql_parser::{parse_query, query::Document};
|
||||
use async_std::task;
|
||||
pub use http::GQLResponse;
|
||||
|
||||
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#"{
|
||||
valueI32 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