use std::convert::TryInto;
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput};
use p2panda_rs::document::DocumentViewId;
use p2panda_rs::entry::decode::decode_entry;
use p2panda_rs::entry::encode::encode_entry;
use p2panda_rs::entry::{EncodedEntry, Entry, EntryBuilder};
use p2panda_rs::hash::Hash;
use p2panda_rs::identity::KeyPair;
use p2panda_rs::operation::decode::decode_operation;
use p2panda_rs::operation::encode::encode_operation;
use p2panda_rs::operation::validate::validate_operation_with_entry;
use p2panda_rs::operation::{EncodedOperation, OperationBuilder};
use p2panda_rs::schema::{FieldType, Schema, SchemaId, SchemaName};
use rand::distributions::Alphanumeric;
use rand::{thread_rng, Rng};
fn run_encode(
payload: &str,
key_pair: &KeyPair,
schema_id: &SchemaId,
) -> (EncodedEntry, EncodedOperation) {
let operation = OperationBuilder::new(schema_id)
.fields(&[("payload", payload.into())])
.build()
.unwrap();
let encoded_operation = encode_operation(&operation).unwrap();
let entry = EntryBuilder::new()
.log_id(&0.into())
.seq_num(&1.try_into().unwrap())
.sign(&encoded_operation, key_pair)
.unwrap();
let encoded_entry = encode_entry(&entry).unwrap();
(encoded_entry, encoded_operation)
}
fn run_decode(encoded_entry: &EncodedEntry, encoded_operation: &EncodedOperation, schema: &Schema) {
let entry = decode_entry(encoded_entry).unwrap();
let plain_operation = decode_operation(encoded_operation).unwrap();
validate_operation_with_entry(
&entry,
encoded_entry,
None::<(&Entry, &Hash)>,
None::<(&Entry, &Hash)>,
&plain_operation,
encoded_operation,
schema,
)
.unwrap();
}
fn random_string(size: usize) -> String {
let mut rng = thread_rng();
(0..size)
.map(|_| rng.sample(Alphanumeric) as char)
.collect()
}
fn get_benchmark_id(function_name: &str, size: &usize) -> BenchmarkId {
static KB: usize = 1024;
let benchmark_parameter = match size > &KB {
false => format!("{} B", size),
true => format!("{} KiB", size / KB),
};
BenchmarkId::new(function_name, benchmark_parameter)
}
fn criterion_benchmark(c: &mut Criterion) {
static KB: usize = 1024;
let key_pair = KeyPair::new();
let schema_view_id = DocumentViewId::new(&[
"00201413ae916e6745ab715c1f5ab49c47d6773c3c0febd970ecf1039beed203b472"
.parse()
.unwrap(),
]);
let schema_name = SchemaName::new("benchmark").expect("Schema name is valid");
let schema_id = SchemaId::Application(schema_name, schema_view_id);
let schema = Schema::new(
&schema_id,
"Payload for measuring performance of encoding, decoding and validation",
&vec![("payload", FieldType::String)],
)
.unwrap();
let mut encode_decode = c.benchmark_group("entry and operation");
for size in [16, KB, 16 * KB, 64 * KB, 256 * KB, 1024 * KB].iter() {
let payload = random_string(*size);
encode_decode.throughput(Throughput::Bytes(*size as u64));
encode_decode.bench_with_input(get_benchmark_id("encode", size), size, |b, &_size| {
b.iter(|| run_encode(&payload, &key_pair, &schema_id))
});
}
for size in [16, KB, 16 * KB, 64 * KB, 256 * KB, 1024 * KB].iter() {
let payload = random_string(*size);
let (entry_encoded, operation_encoded) = run_encode(&payload, &key_pair, &schema_id);
encode_decode.throughput(Throughput::Bytes(*size as u64));
encode_decode.bench_with_input(get_benchmark_id("decode", size), size, |b, &_size| {
b.iter(|| run_decode(&entry_encoded, &operation_encoded, &schema))
});
}
encode_decode.finish();
}
criterion_group!(benches, criterion_benchmark);
criterion_main!(benches);