Skip to content

Commit

Permalink
Merge pull request #15 from itzmeanjan/cycles-per-byte-bench
Browse files Browse the repository at this point in the history
Cycles/ Byte -based Benchmarking
  • Loading branch information
itzmeanjan authored Oct 27, 2023
2 parents c751734 + d93a271 commit 7f6dd60
Show file tree
Hide file tree
Showing 8 changed files with 407 additions and 269 deletions.
15 changes: 9 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "turboshake"
version = "0.1.6"
version = "0.1.7"
edition = "2021"
authors = ["Anjan Roy <hello@itzmeanjan.in>"]
description = "A family of extendable output functions based on keccak-p[1600, 12] permutation"
Expand All @@ -17,13 +17,16 @@ simdx2 = []
simdx4 = []

[dependencies]
crunchy = "0.2.2"
crunchy = "=0.2.2"

[dev-dependencies]
rand = "0.8.5"
hex = "0.4.3"
criterion = "0.4.0"
test-case = "3.0.0"
rand = "=0.8.5"
hex = "=0.4.3"
criterion = "=0.5.1"
test-case = "=3.2.1"

[target.'cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "loongarch64"))'.dev-dependencies]
criterion-cycles-per-byte = {git = "https://github.com/itzmeanjan/criterion-cycles-per-byte", rev = "2dc25c6"}

[lib]
bench = false
Expand Down
429 changes: 224 additions & 205 deletions README.md

Large diffs are not rendered by default.

38 changes: 36 additions & 2 deletions benches/keccak.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,29 @@ use criterion::{black_box, criterion_group, criterion_main, BatchSize, Criterion
use rand::{thread_rng, Rng};
use turboshake::keccak;

#[cfg(any(
target_arch = "x86_64",
target_arch = "x86",
target_arch = "loongarch64"
))]
use criterion_cycles_per_byte::CyclesPerByte;

#[cfg(any(
target_arch = "x86_64",
target_arch = "x86",
target_arch = "loongarch64"
))]
type CriterionHandler = Criterion<CyclesPerByte>;

#[cfg(not(any(
target_arch = "x86_64",
target_arch = "x86",
target_arch = "loongarch64"
)))]
type CriterionHandler = Criterion;

#[cfg(not(any(feature = "simdx2", feature = "simdx4")))]
fn keccak(c: &mut Criterion) {
fn keccak(c: &mut CriterionHandler) {
let mut rng = thread_rng();

let mut group = c.benchmark_group("keccak");
Expand All @@ -30,7 +51,7 @@ fn keccak(c: &mut Criterion) {
}

#[cfg(any(feature = "simdx2", feature = "simdx4"))]
fn keccak(c: &mut Criterion) {
fn keccak(c: &mut CriterionHandler) {
let mut rng = thread_rng();

let mut group = c.benchmark_group("keccak");
Expand Down Expand Up @@ -121,5 +142,18 @@ fn keccak(c: &mut Criterion) {
group.finish();
}

#[cfg(any(
target_arch = "x86_64",
target_arch = "x86",
target_arch = "loongarch64"
))]
criterion_group!(name = permutation; config = Criterion::default().with_measurement(CyclesPerByte); targets = keccak);

#[cfg(not(any(
target_arch = "x86_64",
target_arch = "x86",
target_arch = "loongarch64"
)))]
criterion_group!(permutation, keccak);

criterion_main!(permutation);
162 changes: 106 additions & 56 deletions benches/turboshake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,81 +2,131 @@ use criterion::{black_box, criterion_group, criterion_main, BatchSize, Criterion
use rand::{thread_rng, RngCore};
use turboshake::{TurboShake128, TurboShake256};

fn turboshake128<const MLEN: usize, const DLEN: usize>(c: &mut Criterion) {
#[cfg(any(
target_arch = "x86_64",
target_arch = "x86",
target_arch = "loongarch64"
))]
use criterion_cycles_per_byte::CyclesPerByte;

#[cfg(any(
target_arch = "x86_64",
target_arch = "x86",
target_arch = "loongarch64"
))]
type CriterionHandler = Criterion<CyclesPerByte>;

#[cfg(not(any(
target_arch = "x86_64",
target_arch = "x86",
target_arch = "loongarch64"
)))]
type CriterionHandler = Criterion;

fn turboshake128(c: &mut CriterionHandler) {
const DIGEST_LEN: usize = 64;
const MIN_MSG_LEN: usize = 32;
const MAX_MSG_LEN: usize = 4096;

let mut rng = thread_rng();

let mut group = c.benchmark_group("turboshake128");
group.throughput(Throughput::Bytes(MLEN as u64));
let mut mlen = MIN_MSG_LEN;
while mlen <= MAX_MSG_LEN {
let mut group = c.benchmark_group("turboshake128");
group.throughput(Throughput::Bytes((mlen + DIGEST_LEN) as u64));

group.bench_function(&format!("{}/{} (cached)", MLEN, DLEN), |bench| {
let mut msg = vec![0u8; MLEN];
let mut dig = vec![0u8; DLEN];
rng.fill_bytes(&mut msg);
group.bench_function(&format!("{}/{} (cached)", mlen, DIGEST_LEN), |bench| {
let mut msg = vec![0u8; mlen];
let mut dig = vec![0u8; DIGEST_LEN];
rng.fill_bytes(&mut msg);

bench.iter(|| {
let mut hasher = TurboShake128::new();
hasher.absorb(black_box(&msg));
hasher.finalize::<{ TurboShake128::DEFAULT_DOMAIN_SEPARATOR }>();
hasher.squeeze(black_box(&mut dig));
});
});
group.bench_function(&format!("{}/{} (random)", MLEN, DLEN), |bench| {
let mut msg = vec![0u8; MLEN];
let mut dig = vec![0u8; DLEN];
rng.fill_bytes(&mut msg);

bench.iter_batched(
|| msg.clone(),
|msg| {
bench.iter(|| {
let mut hasher = TurboShake128::new();
hasher.absorb(black_box(&msg));
hasher.finalize::<{ TurboShake128::DEFAULT_DOMAIN_SEPARATOR }>();
hasher.squeeze(black_box(&mut dig));
},
BatchSize::SmallInput,
);
});
});
});
group.bench_function(&format!("{}/{} (random)", mlen, DIGEST_LEN), |bench| {
let mut msg = vec![0u8; mlen];
let mut dig = vec![0u8; DIGEST_LEN];
rng.fill_bytes(&mut msg);

bench.iter_batched(
|| msg.clone(),
|msg| {
let mut hasher = TurboShake128::new();
hasher.absorb(black_box(&msg));
hasher.finalize::<{ TurboShake128::DEFAULT_DOMAIN_SEPARATOR }>();
hasher.squeeze(black_box(&mut dig));
},
BatchSize::SmallInput,
);
});

group.finish();
group.finish();
mlen = 2 * mlen;
}
}

fn turboshake256<const MLEN: usize, const DLEN: usize>(c: &mut Criterion) {
fn turboshake256(c: &mut CriterionHandler) {
const DIGEST_LEN: usize = 64;
const MIN_MSG_LEN: usize = 32;
const MAX_MSG_LEN: usize = 4096;

let mut rng = thread_rng();

let mut group = c.benchmark_group("turboshake256");
group.throughput(Throughput::Bytes(MLEN as u64));
let mut mlen = MIN_MSG_LEN;
while mlen <= MAX_MSG_LEN {
let mut group = c.benchmark_group("turboshake256");
group.throughput(Throughput::Bytes((mlen + DIGEST_LEN) as u64));

group.bench_function(&format!("{}/{} (cached)", MLEN, DLEN), |bench| {
let mut msg = vec![0u8; MLEN];
let mut dig = vec![0u8; DLEN];
rng.fill_bytes(&mut msg);
group.bench_function(&format!("{}/{} (cached)", mlen, DIGEST_LEN), |bench| {
let mut msg = vec![0u8; mlen];
let mut dig = vec![0u8; DIGEST_LEN];
rng.fill_bytes(&mut msg);

bench.iter(|| {
let mut hasher = TurboShake256::new();
hasher.absorb(black_box(&msg));
hasher.finalize::<{ TurboShake128::DEFAULT_DOMAIN_SEPARATOR }>();
hasher.squeeze(black_box(&mut dig));
});
});
group.bench_function(&format!("{}/{} (random)", MLEN, DLEN), |bench| {
let mut msg = vec![0u8; MLEN];
let mut dig = vec![0u8; DLEN];
rng.fill_bytes(&mut msg);

bench.iter_batched(
|| msg.clone(),
|msg| {
bench.iter(|| {
let mut hasher = TurboShake256::new();
hasher.absorb(black_box(&msg));
hasher.finalize::<{ TurboShake128::DEFAULT_DOMAIN_SEPARATOR }>();
hasher.finalize::<{ TurboShake256::DEFAULT_DOMAIN_SEPARATOR }>();
hasher.squeeze(black_box(&mut dig));
},
BatchSize::SmallInput,
);
});
});
});
group.bench_function(&format!("{}/{} (random)", mlen, DIGEST_LEN), |bench| {
let mut msg = vec![0u8; mlen];
let mut dig = vec![0u8; DIGEST_LEN];
rng.fill_bytes(&mut msg);

group.finish();
bench.iter_batched(
|| msg.clone(),
|msg| {
let mut hasher = TurboShake256::new();
hasher.absorb(black_box(&msg));
hasher.finalize::<{ TurboShake256::DEFAULT_DOMAIN_SEPARATOR }>();
hasher.squeeze(black_box(&mut dig));
},
BatchSize::SmallInput,
);
});

group.finish();
mlen = 2 * mlen;
}
}

criterion_group!(hashing, turboshake128<32, 32>, turboshake128<64, 32>, turboshake128<128, 32>, turboshake128<256, 32>, turboshake128<512, 32>, turboshake128<1024, 32>, turboshake128<2048, 32>, turboshake128<4096, 32>, turboshake256<32, 32>, turboshake256<64, 32>, turboshake256<128, 32>, turboshake256<256, 32>, turboshake256<512, 32>, turboshake256<1024, 32>, turboshake256<2048, 32>, turboshake256<4096, 32>);
#[cfg(any(
target_arch = "x86_64",
target_arch = "x86",
target_arch = "loongarch64"
))]
criterion_group!(name = hashing; config = Criterion::default().with_measurement(CyclesPerByte); targets = turboshake128, turboshake256);

#[cfg(not(any(
target_arch = "x86_64",
target_arch = "x86",
target_arch = "loongarch64"
)))]
criterion_group!(hashing, turboshake128, turboshake256);

criterion_main!(hashing);
3 changes: 3 additions & 0 deletions examples/turboshake128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ fn main() {
hasher.finalize::<{ TurboShake128::DEFAULT_DOMAIN_SEPARATOR }>();
hasher.squeeze(&mut dig[..dlen / 2]);
hasher.squeeze(&mut dig[dlen / 2..]);
hasher.reset();

// You may begin the absorb->finalize->squeeze cycle again !

println!("Message: {}", hex::encode(&msg));
println!("Digest: {}", hex::encode(&dig));
Expand Down
3 changes: 3 additions & 0 deletions examples/turboshake256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ fn main() {
hasher.finalize::<{ TurboShake256::DEFAULT_DOMAIN_SEPARATOR }>();
hasher.squeeze(&mut dig[..dlen / 2]);
hasher.squeeze(&mut dig[dlen / 2..]);
hasher.reset();

// You may begin the absorb->finalize->squeeze cycle again !

println!("Message: {}", hex::encode(&msg));
println!("Digest: {}", hex::encode(&dig));
Expand Down
13 changes: 13 additions & 0 deletions src/turboshake128.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,17 @@ impl TurboShake128 {
out,
);
}

/// Given an instance of TurboShake128, this routine can be used for resetting the sponge state,
/// so that one might restart the absorb->finalize->squeeze cycle, on the same object.
///
/// I found, it's sometimes pretty useful. See https://github.com/itzmeanjan/sha3/blob/faef1bd6/include/shake128.hpp#L74-L82
/// and https://github.com/itzmeanjan/kyber/blob/d7c0144d/include/kem.hpp#L106.
#[inline(always)]
pub fn reset(&mut self) {
self.state.fill(0u64);
self.offset = 0;
self.is_ready = usize::MIN;
self.squeezable = 0;
}
}
13 changes: 13 additions & 0 deletions src/turboshake256.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,17 @@ impl TurboShake256 {
out,
);
}

/// Given an instance of TurboShake256, this routine can be used for resetting the sponge state,
/// so that one might restart the absorb->finalize->squeeze cycle, on the same object.
///
/// I found, it's sometimes pretty useful. See https://github.com/itzmeanjan/sha3/blob/faef1bd6/include/shake256.hpp#L74-L82
/// and https://github.com/itzmeanjan/kyber/blob/d7c0144d/include/kem.hpp#L106.
#[inline(always)]
pub fn reset(&mut self) {
self.state.fill(0u64);
self.offset = 0;
self.is_ready = usize::MIN;
self.squeezable = 0;
}
}

0 comments on commit 7f6dd60

Please sign in to comment.