Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexpectedly slow for hashing large when compiling to WASM #303

Open
marcus-pousette opened this issue May 3, 2023 · 4 comments
Open

Unexpectedly slow for hashing large when compiling to WASM #303

marcus-pousette opened this issue May 3, 2023 · 4 comments

Comments

@marcus-pousette
Copy link

marcus-pousette commented May 3, 2023

So I have done a simple lib to wrap this project in WASM
I am trying to understand why I am not getting good performance for hashing large data sizes.

#[wasm_bindgen]
pub fn hash(input_offset: *mut u8, input_length: usize) -> Vec<u8> {
    let input = unsafe {
        std::slice::from_raw_parts(input_offset, input_length )
    };
    blake3::hash(input).as_bytes().to_vec()
}

#[wasm_bindgen]
pub fn alloc(len: usize) -> *mut u8 {
    let mut buf = Vec::with_capacity(len);
    let ptr = buf.as_mut_ptr();
    std::mem::forget(buf);
    return ptr;
}

It performs great when I run it on input lengths of a few < 5 kb in comparison to Node's sha256 implementation
For 1kb data it is 5x faster.
For 10kb it is a little slower
For 1 mb of data, it is 3x slower.

Is this expected results considering the runtime, perhaps the single threaded nature?

I same performance with the js lib blake3. It performs just as good/bad.

Is there anything I can do to improve this?

@marcus-pousette marcus-pousette changed the title Unexpectly slow for hashing large when compiling to WASM Unexpectedly slow for hashing large when compiling to WASM May 3, 2023
@oconnor663
Copy link
Member

Hmm, that's not expected, and I'm not sure what might cause it. Is there any chance that memory leak in your alloc function is compounding over lots of iterations? Could you give me a complete benchmark script to try it out on my end?

@marcus-pousette
Copy link
Author

marcus-pousette commented May 5, 2023

https://github.com/dao-xyz/blake3-wasm

I created a repo only with the minimal things.

Currently I can not even run it for more than 1 benchmark with the minimal hash function like this

#[wasm_bindgen]
pub fn hash(data: &[u8]) -> Vec<u8> {
    blake3::hash(data).as_bytes().to_vec()
}

I get following error code upon next benchmark

error Command failed with signal "SIGBUS".

Previously with this repo, I also observed the behaviour when I run the benchmark multiple times with the same data size to hash, it becomes slower and slower and sometimes crash with error "bus error". Now however, I can not reproduce that since I for some reason can not do multiple iterations anymore before I get the SIGBUS error.

I am using Node 19.3.0 currently, but get the same behaviour on 18.12.1

@marcus-pousette
Copy link
Author

marcus-pousette commented May 5, 2023

So when I run the benchmark asynchronously/concurrent hash calls it fails with the SIGBUS error

i.e.

 suite.add("hash wasm simple" + size / 1e3 + "kb", {
  defer: true,
  fn: (deferred: any) => {

        const rng = getSample(size);
	bhash(rng)
	deferred.resolve();
  },
}); 

sequentially however

 suite.add("hash wasm simple" + size / 1e3 + "kb", {
  fn: () => {
	
	const rng = getSample(size);
	bhash(rng)
	 
  },
}); 

works an gives following output

sha256, size: 1kb x 149,467 ops/sec ±7.17% (50 runs sampled)
hash wasm simple: 1kb x 708,725 ops/sec ±0.50% (97 runs sampled)
sha256, size: 10kb x 70,460 ops/sec ±57.01% (62 runs sampled)
hash wasm simple: 10kb x 81,595 ops/sec ±0.49% (93 runs sampled)
sha256, size: 1000kb x 2,419 ops/sec ±0.40% (89 runs sampled)
hash wasm simple: 1000kb x 875 ops/sec ±0.20% (97 runs sampled)

Doing the the hashing according to the rust code provided in the beginning of the issue yields similar performance (or a little worse) than this. In this case I do alloc outside the benchmark. To mitigate if there would be some kind of memory leak

@marcus-pousette
Copy link
Author

marcus-pousette commented May 5, 2023

In case for the performance when the benchmark runs until the end (run non-deferred). I assume that the compiled wasm does not use "wasm simd" which makes it worse when the data sizes increases (?) Maybe related to #187 Still, given the benchmarking results provided in the README in this repo, I would assume the WASM version would still outperform or be on par with sha256 even though it is not as optimized

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants