Closed rakshith-ravi closed 4 months ago
Follow up:
Looks like avx2_cpuid::init()
is not const. I'm gonna investigate further and see if it can be made const though
Okay, I have found a way to do this:
I've basically removed all references to cpu_feat_avx2
, and replaced the self.cpu_feat_avx2.get()
call with avx2_cpuid::get()
. There is a difference in code path this way - Instead of the avx2_cpuid::InitToken
getting initialized when Argon2::new()
is called, it now gets initialized when the actual hashing is done. I'm not sure if this exposes us to any sort of timing attacks, but I don't think it should, since subsequent calls to hash are not affected, will all have a constant AtomicU8
lookup time added to it uniformly.
cargo build
, cargo test
, cargo build --release
and cargo test --release
all works.
Please let me know if you're open to a PR with these changes. Looking forward to hearing from you
It will cause a performance regression because it will call CPUID every time instead of caching the result.
Try running the benchmarks on an AVX2-capable system.
Also: is there some reason you need Argon2
itself to be const that the const constructors of Params
don't suffice for?
Try running the benchmarks on an AVX2-capable system.
How do I do that?
Also: is there some reason you need Argon2 itself to be const that the const constructors of Params don't suffice for?
I feel very daft now. What's Params
again? 😅
Ohhh you mean argon2::Params
. Yeah that works too, but I was just wondering if we can make Argon2
itself const, to see if we can get any perf optimization out of it. Worth a shot I guess?
I don't think there's any way to make it const
without sacrificing performance, since it robs us of our ability to precache information about what CPU features are available
Let me look at this when I'm not on an M2 Mac and see if I can figure out what the performance hit would be.
The avx2_cpuid::get()
call only seems to be doing a simple check with an AtomicU8
. It's a one-time init and every subsequent call to get
would only fetch the same initialized value from a static reference. Would that impact performance that much?
Now that I think about it, I suppose it could impact cache hit ratios? Idk, I wouldn't want to make too many assumptions without benchmarking.
Speaking of which, my PC supports AVX2. Would be happy to run benchmarks and get back to you. Just not sure how to though.
Yeah, it's probably fine, though I do worry about painting ourselves into a corner around other potential future optimizations.
Hmm, yes. That is a fair point. const
functions would significantly limit how much we can do within the function, until rust adds support for it, and I'm not sure that is something we should depend on.
Well, I'm cool with it either way. If making new
const and having a singleton either static or a constant improves performance, I'd be happy to put the PR. If not, we can leave it as it is as well
Ideally, we need something like const_eval_select
. For now, I think a better solution would be too keep code as-is and rely on const params.
Is this something that can help us?
While that looks very helpful for other things, it doesn't help here
Sorry if I don't understand this correctly, but can't we use target_feature = "avx2"
to call different functions based on the target feature?
No, #[target_feature = "avx2"]
informs the compiler that it can use that target feature, and also inline between functions annotated with the same target_feature
(s).
We already use it here: https://github.com/RustCrypto/password-hashes/blob/master/argon2/src/lib.rs#L459
The nice thing about that upstream change is right now any function annotated with target_feature
must be unsafe
, which leads to some unnecessarily unsafe code in some cases. This will allow those functions to be safe (including the one I linked to), which is helpful for other reasons but not for this particular problem.
Closing as "won't fix"
Is it possible to make the
Argon2::new
andnew_with_secret
functions const? That way, we can have a constant / global static reference to the hasher and use that throughout our code.Is this something that's possible? I don't see anything that the
new
function is doing that can't be made const. It pretty much seems to be just assigning fields of the struct, and that's it.Would be happy to put a PR if required