#![feature(custom_test_frameworks)] #![test_runner(criterion::runner)] use artemis::{ default_exchanges::{CacheExchange, DedupExchange}, ClientBuilder, Exchange, ExchangeFactory, Operation, OperationResult, Response }; use artemis_test::get_conference::{get_conference::Variables, GetConference}; use async_trait::async_trait; use criterion::{Criterion, Throughput}; use criterion_macro::criterion; use rand::Rng; use serde::Serialize; use std::{error::Error, time::Duration}; struct DummyFetchExchange; impl ExchangeFactory for DummyFetchExchange { fn build(_next: TNext) -> DummyFetchExchange { Self } } const N_CONCURRENCY: u64 = 100; #[async_trait] impl Exchange for DummyFetchExchange { async fn run( &self, operation: Operation ) -> Result> { use artemis_test::get_conference::get_conference::{GetConferenceConference, ResponseData}; let delay = Duration::from_millis(50); tokio::time::delay_for(delay).await; let data = Some(ResponseData { conference: Some(GetConferenceConference { id: "1".to_string(), city: Some("Test City".to_string()), name: "Test Conference".to_string(), talks: Some(Vec::new()) }) }); let result = OperationResult { meta: operation.meta, response: Response { data: Some(serde_json::to_value(data).unwrap()), debug_info: None, errors: None } }; Ok(result) } } #[criterion(create_criterion())] pub fn benchmark_random_queries(c: &mut Criterion) { let url = "http://localhost:8080/graphql"; let builder = ClientBuilder::new(url) .with_exchange(DummyFetchExchange) .with_exchange(CacheExchange) .with_exchange(DedupExchange); let client = builder.build(); let mut rand = rand::thread_rng(); let mut group = c.benchmark_group("throughput-random"); group.throughput(Throughput::Elements(N_CONCURRENCY)); group.bench_function("random queries", |bencher| { bencher.iter(|| { let futures = (0..N_CONCURRENCY).map(|_| { let id: u32 = rand.gen(); let variables = Variables { id: id.to_string() }; client.query(GetConference, variables) }); let all = futures::future::join_all(futures); tokio_test::block_on(all); }) }); } #[criterion(create_criterion())] pub fn benchmark_cached_queries(c: &mut Criterion) { let url = "http://localhost:8080/graphql"; let builder = ClientBuilder::new(url) .with_exchange(DummyFetchExchange) .with_exchange(CacheExchange); let client = builder.build(); let mut rand = rand::thread_rng(); let n = (N_CONCURRENCY / 4) as usize; let variable_set: Vec = (0..n).map(|i| Variables { id: i.to_string() }).collect(); let mut group = c.benchmark_group("throughput-cached"); group.throughput(Throughput::Elements(N_CONCURRENCY)); group.bench_function("cached queries", |bencher| { bencher.iter(|| { let futures = (0..N_CONCURRENCY).map(|_| { let var_id: usize = rand.gen_range(0, n); let variables = variable_set.get(var_id).unwrap().clone(); client.query(GetConference, variables) }); let all = futures::future::join_all(futures); tokio_test::block_on(all); }) }); } #[criterion(create_criterion())] pub fn benchmark_real_world(c: &mut Criterion) { let url = "http://localhost:8080/graphql"; let builder = ClientBuilder::new(url) .with_exchange(DummyFetchExchange) .with_exchange(CacheExchange) .with_exchange(DedupExchange); let client = builder.build(); let n = 20; // Simulate n different queries run randomly multiple times let variable_set: Vec = (0..n).map(|i| Variables { id: i.to_string() }).collect(); let mut rand = rand::thread_rng(); let mut group = c.benchmark_group("throughput-real"); group.throughput(Throughput::Elements(N_CONCURRENCY)); group.bench_function("real world queries", |bencher| { bencher.iter(|| { let futures = (0..N_CONCURRENCY).map(|_| { let var_id: usize = rand.gen_range(0, n); let variables = variable_set.get(var_id).unwrap().clone(); client.query(GetConference, variables) }); let all = futures::future::join_all(futures); tokio_test::block_on(all); }) }); } fn create_criterion() -> Criterion { Criterion::default().sample_size(10) }