Add read benchmarks to the blobstore benchmark set

Summary: This lets us look at a blobstore's behaviour for repeated single reads, parallel same-blob reads, and parallel reads to multiple blobs.

Reviewed By: krallin

Differential Revision: D20920206

fbshipit-source-id: 24d9a58024318ff3454fbbf44d6f461355191c55
This commit is contained in:
Simon Farnsworth 2020-04-13 08:35:01 -07:00 committed by Facebook GitHub Bot
parent 15ae1a5864
commit d11ae2dcc8
4 changed files with 229 additions and 0 deletions

View File

@ -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();

View File

@ -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<dyn Blobstore>,
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<dyn Blobstore>| {
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();
}

View File

@ -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<dyn Blobstore>,
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<dyn Blobstore>| {
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();
}

View File

@ -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<dyn Blobstore>,
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<dyn Blobstore>| {
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();
}