Skip to content

Commit 4ff18e9

Browse files
authored
Parallelize scrypt with rayon (#733)
Implements #79 If `p>1`, then the different RoMix blocks are calculated in parallel, using Rayon. # Benchmarks ## without `rayon` feature ``` test scrypt_17_2_4 ... bench: 270,342,994.10 ns/iter (+/- 37,060,120.60) test scrypt_17_8_1 ... bench: 294,787,189.50 ns/iter (+/- 21,095,956.53) ``` ## with `rayon` feature ``` test scrypt_17_2_4 ... bench: 116,287,221.00 ns/iter (+/- 12,892,179.24) test scrypt_17_8_1 ... bench: 290,716,320.30 ns/iter (+/- 13,595,822.07) ```
1 parent 9eb3ab1 commit 4ff18e9

File tree

4 files changed

+40
-6
lines changed

4 files changed

+40
-6
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scrypt/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ rust-version = "1.85"
1717
pbkdf2 = { version = "0.13.0-rc.1", path = "../pbkdf2" }
1818
salsa20 = { version = "0.11.0-rc.1", default-features = false }
1919
sha2 = { version = "0.11.0-rc.2", default-features = false }
20+
rayon = { version = "1.11", optional = true }
2021

2122
# optional dependencies
2223
password-hash = { version = "0.6.0-rc.1", default-features = false, features = ["rand_core"], optional = true }
@@ -25,8 +26,9 @@ password-hash = { version = "0.6.0-rc.1", default-features = false, features = [
2526
password-hash = { version = "0.6.0-rc.1", features = ["rand_core"] }
2627

2728
[features]
28-
default = ["simple"]
29+
default = ["simple", "rayon"]
2930
simple = ["password-hash"]
31+
rayon = ["dep:rayon"]
3032

3133
[package.metadata.docs.rs]
3234
all-features = true

scrypt/benches/lib.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ extern crate test;
66
use test::Bencher;
77

88
#[bench]
9-
pub fn scrypt_15_8_1(bh: &mut Bencher) {
9+
pub fn scrypt_17_8_1(bh: &mut Bencher) {
1010
let password = b"my secure password";
1111
let salt = b"salty salt";
1212
let mut buf = [0u8; 32];
@@ -16,3 +16,15 @@ pub fn scrypt_15_8_1(bh: &mut Bencher) {
1616
test::black_box(&buf);
1717
});
1818
}
19+
20+
#[bench]
21+
pub fn scrypt_17_2_4(bh: &mut Bencher) {
22+
let password = b"my secure password";
23+
let salt = b"salty salt";
24+
let mut buf = [0u8; 32];
25+
let params = scrypt::Params::new(17, 2, 4).unwrap();
26+
bh.iter(|| {
27+
scrypt::scrypt(password, salt, &params, &mut buf).unwrap();
28+
test::black_box(&buf);
29+
});
30+
}

scrypt/src/lib.rs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,32 @@ pub fn scrypt(
112112
let mut b = vec![0u8; pr128];
113113
pbkdf2_hmac::<Sha256>(password, salt, 1, &mut b);
114114

115+
#[cfg(not(feature = "rayon"))]
116+
romix_sequential(nr128, r128, n, &mut b);
117+
#[cfg(feature = "rayon")]
118+
romix_parallel(nr128, r128, n, &mut b);
119+
120+
pbkdf2_hmac::<Sha256>(password, &b, 1, output);
121+
Ok(())
122+
}
123+
124+
#[cfg(not(feature = "rayon"))]
125+
fn romix_sequential(nr128: usize, r128: usize, n: usize, b: &mut [u8]) {
115126
let mut v = vec![0u8; nr128];
116127
let mut t = vec![0u8; r128];
117128

118-
for chunk in &mut b.chunks_mut(r128) {
129+
b.chunks_mut(r128).for_each(|chunk| {
119130
romix::scrypt_ro_mix(chunk, &mut v, &mut t, n);
120-
}
131+
});
132+
}
121133

122-
pbkdf2_hmac::<Sha256>(password, &b, 1, output);
123-
Ok(())
134+
#[cfg(feature = "rayon")]
135+
fn romix_parallel(nr128: usize, r128: usize, n: usize, b: &mut [u8]) {
136+
use rayon::{iter::ParallelIterator as _, slice::ParallelSliceMut as _};
137+
138+
b.par_chunks_mut(r128).for_each(|chunk| {
139+
let mut v = vec![0u8; nr128];
140+
let mut t = vec![0u8; r128];
141+
romix::scrypt_ro_mix(chunk, &mut v, &mut t, n);
142+
});
124143
}

0 commit comments

Comments
 (0)