-
Notifications
You must be signed in to change notification settings - Fork 16
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
implement crc32 #14
Comments
I started prototyping this, have an MVP for the first item on the list but have some quick comments. First, after reading the docs for Second, how do you feel about quickcheck for testing? It would be pretty useful here. Third, afaict |
Add a naive implementation of CRC-32 based on the C code from the PNG specification.
Add a naive implementation of CRC-32 based on the C code from the PNG specification.
Cool that you're picking this up! The mm_crc32_u32 function is used not for gzip, but for the hash chaining in zlib-ng on systems that support it. I suspect the particulars of what polynomial is used don't particularly matter here, you really just want a fast decent hash.
My proposal would be to just use mm_crc32_u32 as an intrinsic. The fallback is #define HASH_CALC(s, h, val) h = ((val * 2654435761U) >> HASH_SLIDE); which does look different to the intel docs for _mm_crc32_u32. But that does not really matter so long as the same function is used consistently. I was under the impression that the fallback would have the same behavior as _mm_crc32_u32 but that seems to not be the case. We're very mindful of dependencies for the final crate/dynamic library, but I haven't really used quickcheck (in rust, I have in Haskell) but let's give it a go! I think it makes sense to look at the zlib-ng codebase next to see how they implement crc32. We can be reasonably confident they have one of the fastest implementations out there. Navigating this code is not awesome, there is lots of macro expansion that makes it hard to understand what is happening. The generic crc32 implementation is here I think that is a good jumping-off point. You'll need some other things like the huge tables that crc32 uses, they are in that repository as well. Also it's probably a good thing to look at what architecture-specific features are implemented (in particular the type signatures). |
Very sorry if this is a dumb question. Andrei and I (Per) were taking last night and we weren't sure what your concerns with |
Add a naive implementation of CRC-32 based on the C code from the PNG specification.
No that is a very reasonable question. Many things are coming together here
In this particular case, I think
So, I'd be totally happy to use Separately I'm a big fan of upstreaming features we do add. does that make sense? |
yes. Thank you for explaining the reasoning. I agree that supply chain attacks is something that must be prevented. However, as we've discussed, vendoring crates or relying on crate versions that have been vetted might be worth considering as a general approach. Google has open sourced their crate audits and it includes Of course that doesn't address your concern that the crate doesn't do everything needed so I am not arguing that for this particular case, using an existing crate is optimal. Putting that aside, how do you think about a general policy of "have as few dependencies as a general rule but reuse functionality available from mature and audited crates"? [0] https://github.com/google/rust-crate-audits/blob/main/manual-sources/google3-audits.toml |
Add a naive implementation of CRC-32 based on the C code from the PNG specification. Add an optimized word-size implementation based on Kadatch and Jenkins. Add optimized interleaved implementation from section 4.11 of the same paper.
Add a naive implementation of CRC-32 based on the C code from the PNG specification. Add an optimized word-size implementation based on Kadatch and Jenkins. Add optimized interleaved implementation from section 4.11 of the same paper.
I think my personal taste is to be quite hardcore about owning the logic that is core to your project. You should know how it works, and it's likely that you can be more efficient than a generic solution when you have a specific problem. As an example,
Of course you have to be pragmatic, but given how easy it is to accumulate dependencies, I think being skeptical of adding one is the right baseline. btw for what dependencies we use we mostly go by popularity in the rust ecosystem (clap, tokio, rustls are all widely used and actively maintained), occasionally informed by packaging concerns (this can also be a reason not to upgrade a dependency). So far we've not had reasons to stick to a particular list of audited libraries, but that seems like a decent approach that saves you quite a bit of work. |
Add a naive implementation of CRC-32 based on the C code from the PNG specification. Add an optimized word-size implementation based on Kadatch and Jenkins. Add optimized interleaved implementation from section 4.11 of the same paper.
Add a naive implementation of CRC-32 based on the C code from the PNG specification. Add an optimized word-size implementation based on Kadatch and Jenkins. Add optimized interleaved implementation from section 4.11 of the same paper.
Add a naive implementation of CRC-32 based on the C code from the PNG specification. Add an optimized word-size implementation based on Kadatch and Jenkins. Add optimized interleaved implementation from section 4.11 of the same paper.
Add a naive implementation of CRC-32 based on the C code from the PNG specification. Add an optimized word-size implementation based on Kadatch and Jenkins. Add optimized interleaved implementation from section 4.11 of the same paper.
Add a naive implementation of CRC-32 based on the C code from the PNG specification. Add an optimized word-size implementation based on Kadatch and Jenkins. Add optimized interleaved implementation from section 4.11 of the same paper.
Add a naive implementation of CRC-32 based on the C code from the PNG specification. Add an optimized word-size implementation based on Kadatch and Jenkins. Add optimized interleaved implementation from section 4.11 of the same paper.
Is anyone still working on a pure-Rust crc32 implementation? If not, I'm willing to try creating two implementations: a simple, slow version as a baseline, and then a fast version inspired by the one in zlib-ng. And should it be CRC32 or CRC32-C? It seems like the current implementation in |
we have a pure-rust implementation, that has the expected simd support on the targets we care most about. The implementation lives here. However, if you believe you can make it faster, or support more platforms, by all means have a got at that. For the logic in We've been working on proper benchmarking (on dedicated hardware (apple m2 and a recent amd), with graphs etc), so we'll be in a much better shape data-wise to evaluate the various options. |
std::arch::x86_64::_mm_crc32_u32
intrinsic into the crc32 module, make it platform-independent (/src/deflate/hash_calc.rs
).Then of course we also need simd-accelerated versions. zlib-ng has several in the
/arch
folder. In rust there is https://docs.rs/crc32fast/latest/crc32fast/. I don't think we want that as a dependency but it may provide inspiration.The text was updated successfully, but these errors were encountered: