Най-накрая още някой да подхване ръст
Проблема ти е, че алокира памет. А пък валидира байтаррея и пак алокира нов стринг. С минимална промяна могат да се избегнат 2те излишни алокации и валидацията и става по-бързо:
CODE |
pub fn hash_optimized_2(input: &str, times: usize) -> String { assert!(times > 0);
let mut hasher: Sha1 = Sha1::new(); let mut raw_out = [0; 20]; let mut hex_out = [0; 40];
hasher.input(input.as_bytes()); hasher.result(&mut raw_out); hasher.reset(); as_hex(&raw_out, &mut hex_out);
for _ in 1..times { hasher.input(&hex_out); hasher.result(&mut raw_out); hasher.reset(); as_hex(&raw_out, &mut hex_out); }
return from_utf8(&hex_out).expect("Error: UTF").to_string(); }
fn as_hex(src: &[u8; 20], dst: &mut [u8; 40]) { const HEX: [u8; 16] = [ b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'a', b'b', b'c', b'd', b'e', b'f', ];
for idx in 0..src.len() { let hi = (src[idx] >> 4) as usize; let lo = (src[idx] & 0x0F) as usize;
dst[idx * 2] = HEX[hi]; dst[idx * 2 + 1] = HEX[lo] } }
|
Benchmark:
CODE | use criterion::{black_box, criterion_group, criterion_main, Criterion}; use rs::{hash_optimized, hash_optimized_2, hash_repeatedly};
criterion_group!(benches, benchmark); criterion_main!(benches);
pub fn benchmark(c: &mut Criterion) { c.bench_function("A", |b| { b.iter(|| black_box(hash_repeatedly(black_box("hello world"), black_box(1000)))) });
c.bench_function("B", |b| { b.iter(|| black_box(hash_optimized(black_box("hello world"), black_box(1000)))) });
c.bench_function("C", |b| { b.iter(|| black_box(hash_optimized_2(black_box("hello world"), black_box(1000)))) }); }
|
Results:
CODE | A time: [191.26 us 191.49 us 191.72 us] // оригиналната версия B time: [228.07 us 228.34 us 228.62 us] // след "оптимизацията" C time: [154.22 us 154.47 us 154.73 us] // моята |
|