Skip to content

Commit

Permalink
Merge pull request #66 from stackhpc/operation-bench
Browse files Browse the repository at this point in the history
Add operations benchmark
  • Loading branch information
markgoddard authored Aug 3, 2023
2 parents 8e4be4a + 6759667 commit 7fb6883
Show file tree
Hide file tree
Showing 11 changed files with 129 additions and 40 deletions.
16 changes: 16 additions & 0 deletions .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,22 @@ jobs:

- name: Build
run: make build
docs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Build documentation
run: make docs
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Lint
run: make lint
test:
runs-on: ubuntu-latest
steps:
Expand Down
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ serde_test = "1.0"
name = "byte_order"
harness = false

[[bench]]
name = "operations"
harness = false

[[bench]]
name = "shuffle"
harness = false
Expand Down
12 changes: 10 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,20 @@
build:
@docker buildx build -t reductionist .

.PHONY: docs
docs:
@docker buildx build --build-arg PROFILE=dev --target builder -t reductionist-test .
@docker run --rm -e RUSTDOCFLAGS="-D warnings" reductionist-test cargo doc --no-deps

.PHONY: lint
lint:
@docker buildx build --build-arg PROFILE=dev --target builder -t reductionist-test .
@docker run --rm reductionist-test cargo check --color always

.PHONY: test
test:
@docker buildx build --build-arg PROFILE=dev --target builder -t reductionist-test .
@docker run --rm reductionist-test cargo check --color always
@docker run --rm reductionist-test cargo test --color always
@docker run --rm reductionist-test cargo bench --color always

.PHONY: run
run:
Expand Down
9 changes: 5 additions & 4 deletions benches/compression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use axum::body::Bytes;
use flate2::read::{GzEncoder, ZlibEncoder};
use flate2::Compression;
use std::io::Read;
// Bring trait into scope to use as_bytes method.
use zerocopy::AsBytes;

fn compress_gzip(data: &[u8]) -> Bytes {
// Adapated from flate2 documentation.
Expand Down Expand Up @@ -39,10 +41,9 @@ fn criterion_benchmark(c: &mut Criterion) {
for (compression, name) in compression_algs {
for size_k in [64, 256, 1024] {
let size = size_k * 1024;
let data: Vec<u8> = (0_u32..size)
.map(|i| u8::try_from(i % 256).unwrap())
.collect::<Vec<u8>>();
let compressed = compress(compression, data.as_ref());
let data: Vec<i64> = (0_i64..size).map(|i| i % 256).collect::<Vec<i64>>();
let bytes = Bytes::copy_from_slice(data.as_bytes());
let compressed = compress(compression, &bytes);
let name = format!("decompress({}, {})", name, size);
c.bench_function(&name, |b| {
b.iter(|| {
Expand Down
69 changes: 69 additions & 0 deletions benches/operations.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/// Benchmarks for numerical operations.
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use reductionist::error::ActiveStorageError;
use reductionist::models::{DType, RequestData, Response};
use reductionist::operation::Operation;
use reductionist::operations;
use reductionist::types::Missing;
use url::Url;
// Bring trait into scope to use as_bytes method.
use zerocopy::AsBytes;

fn get_test_request_data() -> RequestData {
RequestData {
source: Url::parse("http://example.com").unwrap(),
bucket: "bar".to_string(),
object: "baz".to_string(),
dtype: DType::Int32,
byte_order: None,
offset: None,
size: None,
shape: None,
order: None,
selection: None,
compression: None,
filters: None,
missing: None,
}
}

type ExecuteFn = dyn Fn(&RequestData, Vec<u8>) -> Result<Response, ActiveStorageError>;

fn criterion_benchmark(c: &mut Criterion) {
for size_k in [64, 256, 1024, 4096] {
let size = size_k * 1024;
let data: Vec<i64> = (0_i64..size).map(|i| i % 256).collect::<Vec<i64>>();
let data: Vec<u8> = data.as_bytes().into();
let missings = vec![
None,
Some(Missing::MissingValue(42.into())),
Some(Missing::MissingValues(vec![42.into()])),
Some(Missing::ValidMax(128.into())),
Some(Missing::ValidMin(128.into())),
Some(Missing::ValidRange(5.into(), 250.into())),
];
let operations: [(&str, Box<ExecuteFn>); 5] = [
("count", Box::new(operations::Count::execute)),
("max", Box::new(operations::Max::execute)),
("min", Box::new(operations::Min::execute)),
("select", Box::new(operations::Select::execute)),
("sum", Box::new(operations::Sum::execute)),
];
for (op_name, execute) in operations {
for missing in missings.clone() {
let name = format!("{}({}, {:?})", op_name, size, missing);
c.bench_function(&name, |b| {
b.iter(|| {
let mut request_data = get_test_request_data();
request_data.dtype = DType::Int64;
request_data.missing = missing.clone();
execute(&request_data, black_box(data.clone())).unwrap();
})
});
}
}
}
}

criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);
11 changes: 6 additions & 5 deletions benches/shuffle.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
/// Benchmarks for the byte shuffle filter implementation.
use axum::body::Bytes;
use criterion::{black_box, criterion_group, criterion_main, Criterion};
use reductionist::filters::shuffle;
// Bring trait into scope to use as_bytes method.
use zerocopy::AsBytes;

fn criterion_benchmark(c: &mut Criterion) {
for size_k in [64, 256, 1024] {
for size_k in [64, 256, 1024, 4096] {
let size = size_k * 1024;
let data: Vec<u8> = (0_u32..size)
.map(|i| u8::try_from(i % 256).unwrap())
.collect::<Vec<u8>>();
let bytes = data.into();
let data: Vec<i64> = (0_i64..size).map(|i| i % 256).collect::<Vec<i64>>();
let bytes = Bytes::copy_from_slice(data.as_bytes());
for element_size in [2, 4, 8] {
let name = format!("deshuffle({}, {})", size, element_size);
c.bench_function(&name, |b| {
Expand Down
4 changes: 2 additions & 2 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,8 @@ fn router() -> Router {

/// Reductionist Server Service type alias
///
/// This type implements [tower_service::Service].
// FIXME: The Service type should be some form of tower_service::Service, but couldn't find the
/// This type implements [tower::Service].
// FIXME: The Service type should be some form of tower::Service, but couldn't find the
// necessary trait bounds.
pub type Service = tower_http::normalize_path::NormalizePath<Router>;

Expand Down
30 changes: 6 additions & 24 deletions src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,65 +218,47 @@ mod tests {
let value: u32 = 42;
let mut buf = maligned::align_first::<u8, maligned::A4>(4);
buf.extend_from_slice(&value.to_ne_bytes());
assert_eq!(
[value],
from_bytes::<u32>(&mut buf).unwrap()
);
assert_eq!([value], from_bytes::<u32>(&mut buf).unwrap());
}

#[test]
fn from_bytes_u64() {
let value: u64 = u64::max_value();
let mut buf = maligned::align_first::<u8, maligned::A8>(8);
buf.extend_from_slice(&value.to_ne_bytes());
assert_eq!(
[value],
from_bytes::<u64>(&mut buf).unwrap()
);
assert_eq!([value], from_bytes::<u64>(&mut buf).unwrap());
}

#[test]
fn from_bytes_i32() {
let value: i32 = -42;
let mut buf = maligned::align_first::<u8, maligned::A4>(4);
buf.extend_from_slice(&value.to_ne_bytes());
assert_eq!(
[value],
from_bytes::<i32>(&mut buf).unwrap()
);
assert_eq!([value], from_bytes::<i32>(&mut buf).unwrap());
}

#[test]
fn from_bytes_i64() {
let value: i64 = i64::min_value();
let mut buf = maligned::align_first::<u8, maligned::A8>(8);
buf.extend_from_slice(&value.to_ne_bytes());
assert_eq!(
[value],
from_bytes::<i64>(&mut buf).unwrap()
);
assert_eq!([value], from_bytes::<i64>(&mut buf).unwrap());
}

#[test]
fn from_bytes_f32() {
let value: f32 = f32::min_value();
let mut buf = maligned::align_first::<u8, maligned::A4>(4);
buf.extend_from_slice(&value.to_ne_bytes());
assert_eq!(
[value],
from_bytes::<f32>(&mut buf).unwrap()
);
assert_eq!([value], from_bytes::<f32>(&mut buf).unwrap());
}

#[test]
fn from_bytes_f64() {
let value: f64 = f64::max_value();
let mut buf = maligned::align_first::<u8, maligned::A8>(8);
buf.extend_from_slice(&value.to_ne_bytes());
assert_eq!(
[value],
from_bytes::<f64>(&mut buf).unwrap()
);
assert_eq!([value], from_bytes::<f64>(&mut buf).unwrap());
}

fn assert_from_bytes_error<T: std::fmt::Debug>(result: Result<T, ActiveStorageError>) {
Expand Down
2 changes: 1 addition & 1 deletion src/operation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ pub trait Operation {
/// # Arguments
///
/// * `request_data`: RequestData object for the request
/// * `data`: Vec<u8> containing data to operate on.
/// * `data`: [`Vec<u8>`] containing data to operate on.
fn execute(
request_data: &models::RequestData,
data: Vec<u8>,
Expand Down
6 changes: 4 additions & 2 deletions src/types/missing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ pub enum Missing<T> {
}

impl Missing<DValue> {
/// Validate a Missing<DValue> object for a given DType.
/// Validate a [`Missing<DValue>`](crate::types::Missing) object for a given
/// [DType](crate::models::DType).
pub fn validate(&self, dtype: DType) -> Result<(), ValidationError> {
match dtype {
DType::Int32 => Missing::<i32>::validate_dvalue(self),
Expand All @@ -44,7 +45,8 @@ impl Missing<DValue> {
}

impl<T: PartialOrd + Serialize + TryFromDValue> Missing<T> {
/// Validate a Missing<DValue> for Missing<T> where T is a supported primitive numeric type.
/// Validate a [`Missing<DValue>`](crate::types::Missing) for Missing<T> where T is a supported
/// primitive numeric type.
fn validate_dvalue(missing: &Missing<DValue>) -> Result<(), ValidationError> {
// Perform a conversion to the primitive based type.
let missing_primitive = Self::try_from(missing).map_err(|err| {
Expand Down
6 changes: 6 additions & 0 deletions tools/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,10 @@ then
exit 1
fi

if ! RUSTDOCFLAGS="-D warnings" cargo doc --no-deps
then
echo "There are some documentation issues."
exit 1
fi

exit 0

0 comments on commit 7fb6883

Please sign in to comment.