diff --git a/eden/mononoke/cmds/benchmark_storage_config/main.rs b/eden/mononoke/cmds/benchmark_storage_config/main.rs index dd551612df..2b978b27d6 100644 --- a/eden/mononoke/cmds/benchmark_storage_config/main.rs +++ b/eden/mononoke/cmds/benchmark_storage_config/main.rs @@ -19,6 +19,10 @@ use context::CoreContext; mod parallel_puts; mod single_puts; +mod parallel_different_blob_gets; +mod parallel_same_blob_gets; +mod single_gets; + pub const KB: usize = 1024; pub const MB: usize = KB * 1024; const ARG_STORAGE_CONFIG_NAME: &'static str = "storage-config-name"; @@ -112,6 +116,19 @@ fn main(fb: fbinit::FacebookInit) { // Tests are run from here single_puts::benchmark(&mut criterion, ctx.clone(), blobstore.clone(), &mut runtime); parallel_puts::benchmark(&mut criterion, ctx.clone(), blobstore.clone(), &mut runtime); + single_gets::benchmark(&mut criterion, ctx.clone(), blobstore.clone(), &mut runtime); + parallel_same_blob_gets::benchmark( + &mut criterion, + ctx.clone(), + blobstore.clone(), + &mut runtime, + ); + parallel_different_blob_gets::benchmark( + &mut criterion, + ctx.clone(), + blobstore.clone(), + &mut runtime, + ); runtime.shutdown_on_idle(); criterion.final_summary(); diff --git a/eden/mononoke/cmds/benchmark_storage_config/parallel_different_blob_gets.rs b/eden/mononoke/cmds/benchmark_storage_config/parallel_different_blob_gets.rs new file mode 100644 index 0000000000..96ec9de2fb --- /dev/null +++ b/eden/mononoke/cmds/benchmark_storage_config/parallel_different_blob_gets.rs @@ -0,0 +1,79 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This software may be used and distributed according to the terms of the + * GNU General Public License version 2. + */ + +use std::{iter::repeat, sync::Arc}; + +use criterion::{BenchmarkId, Criterion, Throughput}; +use futures::{ + compat::Future01CompatExt, + stream::{FuturesUnordered, TryStreamExt}, +}; +use rand::{thread_rng, Rng, RngCore}; +use tokio_compat::runtime::Runtime; + +use blobstore::{Blobstore, BlobstoreBytes}; +use context::CoreContext; + +use crate::{KB, MB}; + +pub fn benchmark( + c: &mut Criterion, + ctx: CoreContext, + blobstore: Arc, + runtime: &mut Runtime, +) { + let mut group = c.benchmark_group("parallel_different_blob_gets"); + + for size in [128, 16 * KB, 512 * KB, 8 * MB].iter() { + for concurrency in [4, 16, 256].iter() { + group.throughput(Throughput::Bytes(*size as u64 * *concurrency as u64)); + group.bench_with_input( + BenchmarkId::from_parameter(format!("{} x{}", size, concurrency)), + size, + |b, &size| { + let keys: Vec<_> = repeat(()) + .take(*concurrency) + .map(|()| { + let mut block = Vec::with_capacity(size); + block.resize(size, 0u8); + thread_rng().fill(&mut block as &mut [u8]); + + let block = BlobstoreBytes::from_bytes(block); + let key = format!("benchmark.{:x}", thread_rng().next_u64()); + runtime.block_on_std(async { + blobstore + .put(ctx.clone(), key.clone(), block) + .compat() + .await + .expect("Put failed") + }); + key + }) + .collect(); + let test = |ctx: CoreContext, blobstore: Arc| { + let keys = keys.clone(); + async move { + let futs: FuturesUnordered<_> = keys + .into_iter() + .map(|key| blobstore.get(ctx.clone(), key).compat()) + .collect(); + futs.try_for_each(|_| async move { Ok(()) }) + .await + .expect("Gets failed"); + } + }; + b.iter(|| { + runtime + .block_on_std(async { test(ctx.clone(), Arc::clone(&blobstore)).await }) + }); + }, + ); + } + } + + group.finish(); +} diff --git a/eden/mononoke/cmds/benchmark_storage_config/parallel_same_blob_gets.rs b/eden/mononoke/cmds/benchmark_storage_config/parallel_same_blob_gets.rs new file mode 100644 index 0000000000..599b6e7cbc --- /dev/null +++ b/eden/mononoke/cmds/benchmark_storage_config/parallel_same_blob_gets.rs @@ -0,0 +1,73 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This software may be used and distributed according to the terms of the + * GNU General Public License version 2. + */ + +use std::{iter::repeat, sync::Arc}; + +use criterion::{BenchmarkId, Criterion, Throughput}; +use futures::{ + compat::Future01CompatExt, + stream::{FuturesUnordered, TryStreamExt}, +}; +use rand::{thread_rng, Rng, RngCore}; +use tokio_compat::runtime::Runtime; + +use blobstore::{Blobstore, BlobstoreBytes}; +use context::CoreContext; + +use crate::{KB, MB}; + +pub fn benchmark( + c: &mut Criterion, + ctx: CoreContext, + blobstore: Arc, + runtime: &mut Runtime, +) { + let mut group = c.benchmark_group("parallel_same_blob_gets"); + + for size in [128, 16 * KB, 512 * KB, 8 * MB].iter() { + for concurrency in [4, 16, 256].iter() { + group.throughput(Throughput::Bytes(*size as u64 * *concurrency as u64)); + group.bench_with_input( + BenchmarkId::from_parameter(format!("{} x{}", size, concurrency)), + size, + |b, &size| { + let mut block = Vec::with_capacity(size); + block.resize(size, 0u8); + thread_rng().fill(&mut block as &mut [u8]); + + let block = BlobstoreBytes::from_bytes(block); + let key = format!("benchmark.{:x}", thread_rng().next_u64()); + runtime.block_on_std(async { + blobstore + .put(ctx.clone(), key.clone(), block) + .compat() + .await + .expect("Put failed") + }); + let keys = repeat(key).take(*concurrency); + let test = |ctx: CoreContext, blobstore: Arc| { + let keys = keys.clone(); + async move { + let futs: FuturesUnordered<_> = keys + .map(|key| blobstore.get(ctx.clone(), key).compat()) + .collect(); + futs.try_for_each(|_| async move { Ok(()) }) + .await + .expect("Gets failed"); + } + }; + b.iter(|| { + runtime + .block_on_std(async { test(ctx.clone(), Arc::clone(&blobstore)).await }) + }); + }, + ); + } + } + + group.finish(); +} diff --git a/eden/mononoke/cmds/benchmark_storage_config/single_gets.rs b/eden/mononoke/cmds/benchmark_storage_config/single_gets.rs new file mode 100644 index 0000000000..d39548bfff --- /dev/null +++ b/eden/mononoke/cmds/benchmark_storage_config/single_gets.rs @@ -0,0 +1,60 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This software may be used and distributed according to the terms of the + * GNU General Public License version 2. + */ + +use std::sync::Arc; + +use criterion::{BenchmarkId, Criterion, Throughput}; +use futures::compat::Future01CompatExt; +use rand::{thread_rng, Rng, RngCore}; +use tokio_compat::runtime::Runtime; + +use blobstore::{Blobstore, BlobstoreBytes}; +use context::CoreContext; + +use crate::{KB, MB}; + +pub fn benchmark( + c: &mut Criterion, + ctx: CoreContext, + blobstore: Arc, + runtime: &mut Runtime, +) { + let mut group = c.benchmark_group("single_gets"); + + for size in [128, 16 * KB, 512 * KB, 8 * MB].iter() { + group.throughput(Throughput::Bytes(*size as u64)); + group.bench_with_input(BenchmarkId::from_parameter(size), size, |b, &size| { + let mut block = Vec::with_capacity(size); + block.resize(size, 0u8); + thread_rng().fill(&mut block as &mut [u8]); + + let block = BlobstoreBytes::from_bytes(block); + let key = format!("benchmark.{:x}", thread_rng().next_u64()); + runtime.block_on_std(async { + blobstore + .put(ctx.clone(), key.clone(), block) + .compat() + .await + .expect("Put failed") + }); + let test = |ctx, blobstore: Arc| { + let key = &key; + async move { + blobstore + .get(ctx, key.clone()) + .compat() + .await + .expect("Get failed"); + } + }; + b.iter(|| { + runtime.block_on_std(async { test(ctx.clone(), Arc::clone(&blobstore)).await }) + }); + }); + } + group.finish(); +}