From 11808c6356c2a5966ddaeb18341fcdc2290c9179 Mon Sep 17 00:00:00 2001 From: Stuart Stock Date: Sat, 17 Feb 2018 11:39:08 -0600 Subject: Add benchmarks for message and response creation As `[bench]` isn't in stable Rust yet, use [Criterion.rs]https://github.com/japaric/criterion.rs) as the benchmarking harness. --- Cargo.toml | 6 +++ benches/messages.rs | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/message.rs | 2 +- 3 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 benches/messages.rs diff --git a/Cargo.toml b/Cargo.toml index c29f852..57bd058 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,3 +21,9 @@ fern = "0.4" yaml-rust = "0.3.5" ctrlc = { version = "3.0", features = ["termination"] } +[dev-dependencies] +criterion = "0.2.0" + +[[bench]] +name = "messages" +harness = false diff --git a/benches/messages.rs b/benches/messages.rs new file mode 100644 index 0000000..3acd493 --- /dev/null +++ b/benches/messages.rs @@ -0,0 +1,141 @@ +#[macro_use] +extern crate criterion; +extern crate roughenough; +extern crate ring; +extern crate byteorder; +extern crate time; + +use ring::digest; +use ring::rand::SecureRandom; +use byteorder::{LittleEndian, WriteBytesExt}; +use criterion::{Criterion, black_box}; + +use roughenough::{RtMessage, Tag}; +use roughenough::{SIGNED_RESPONSE_CONTEXT, TREE_LEAF_TWEAK}; +use roughenough::sign::Signer; + +fn single_field(data: &[u8]) -> RtMessage { + let mut msg = RtMessage::new(1); + msg.add_field(Tag::NONC, &data[0..63]).unwrap(); + msg +} + +fn two_fields(data: &[u8]) -> RtMessage { + let mut msg = RtMessage::new(2); + msg.add_field(Tag::NONC, &data[0..63]).unwrap(); + msg.add_field(Tag::PAD, &data[64..127]).unwrap(); + msg +} + +// Full-sized server response +fn five_fields(data: &[u8]) -> RtMessage { + let mut response = RtMessage::new(5); + response.add_field(Tag::SIG, &data[0..63]).unwrap(); + response.add_field(Tag::PATH, &data[64..127]).unwrap(); + response.add_field(Tag::SREP, &data[128..191]).unwrap(); + response.add_field(Tag::CERT, &data[192..255]).unwrap(); + response.add_field(Tag::INDX, &data[256..319]).unwrap(); + + response +} + +/// Random data for composing a response +fn make_data(len: usize) -> Vec { + let rng = ring::rand::SystemRandom::new(); + let mut tmp = vec![1u8; len]; + rng.fill(&mut tmp).unwrap(); + + tmp +} + +fn message_creation(c: &mut Criterion) { + let data = make_data(320); + + // TODO(stuart) .to_vec()'s below because I'm fighting the borrow-checker. + // Tried iter_with_setup(), but haven't found the right combo of 'move' + // and reference lifetime(s) yet. + + let d1 = data.to_vec(); + c.bench_function("single field", + move |b| b.iter(|| black_box(single_field(&d1))), + ); + + let d2 = data.to_vec(); + c.bench_function("two fields", + move |b| b.iter(|| black_box(two_fields(&d2))), + ); + + let d3 = data.to_vec(); + c.bench_function("five fields", + move |b| b.iter(|| black_box(five_fields(&d3))), + ); +} + +/// TODO(stuart) straight-up copied form src/bin/server.rs, not ideal at all +fn make_response(ephemeral_key: &mut Signer, cert_bytes: &[u8], nonce: &[u8]) -> RtMessage { + let path = [0u8; 0]; + let zeros = [0u8; 4]; + + let mut radi: Vec = Vec::with_capacity(4); + let mut midp: Vec = Vec::with_capacity(8); + + // one second (in microseconds) + radi.write_u32::(1000000).unwrap(); + + // current epoch time in microseconds + let now = { + let tv = time::get_time(); + let secs = (tv.sec as u64) * 1000000; + let nsecs = (tv.nsec as u64) / 1000; + + secs + nsecs + }; + midp.write_u64::(now).unwrap(); + + // Signed response SREP + let srep_bytes = { + // hash request nonce + let mut ctx = digest::Context::new(&digest::SHA512); + ctx.update(&TREE_LEAF_TWEAK); + ctx.update(&nonce); + let digest = ctx.finish(); + + let mut srep_msg = RtMessage::new(3); + srep_msg.add_field(Tag::RADI, &radi).unwrap(); + srep_msg.add_field(Tag::MIDP, &midp).unwrap(); + srep_msg.add_field(Tag::ROOT, digest.as_ref()).unwrap(); + + srep_msg.encode().unwrap() + }; + + // signature on SREP + let srep_signature = { + ephemeral_key.update(SIGNED_RESPONSE_CONTEXT.as_bytes()); + ephemeral_key.update(&srep_bytes); + ephemeral_key.sign() + }; + + let mut response = RtMessage::new(5); + response.add_field(Tag::SIG, &srep_signature).unwrap(); + response.add_field(Tag::PATH, &path).unwrap(); + response.add_field(Tag::SREP, &srep_bytes).unwrap(); + response.add_field(Tag::CERT, cert_bytes).unwrap(); + response.add_field(Tag::INDX, &zeros).unwrap(); + + response +} + +fn response_creation(c: &mut Criterion) { + let nonce = make_data(64); + let cert = make_data(152); + let seed = make_data(32); + let mut signer = Signer::new(&seed); + + c.bench_function("server response", + move |b| b.iter(|| black_box(make_response(&mut signer, &cert, &nonce))), + ); +} + +criterion_group!(benches, message_creation, response_creation); +criterion_main!(benches); + diff --git a/src/message.rs b/src/message.rs index 82e759f..2bbbb45 100644 --- a/src/message.rs +++ b/src/message.rs @@ -98,7 +98,7 @@ impl RtMessage { } // check we wrote exactly what we expected - assert!(out.len() == self.encoded_size(), "unexpected length"); + assert_eq!(out.len(), self.encoded_size(), "unexpected length"); Ok(out) } -- cgit v1.2.3