Skip to content

Commit

Permalink
Change construction to allow stable hashes even with AVX2 and use it …
Browse files Browse the repository at this point in the history
…in a hybrid way for maximum performance
  • Loading branch information
ogxd committed Dec 23, 2023
1 parent a987217 commit 6c555a9
Show file tree
Hide file tree
Showing 17 changed files with 515 additions and 273 deletions.
26 changes: 19 additions & 7 deletions .github/workflows/bench.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,30 @@ jobs:
- uses: actions/checkout@v4

- name: Benchmark
run: cargo bench --bench throughput --features 'bench-plot'
run: cargo bench --bench throughput --features bench-plot

- uses: actions/upload-artifact@v3
with:
name: benches
path: benches/throughput/x86_64.svg

benchmark-x86-avx2:
name: Benchmark X86 AVX2
runs-on: buildjet-2vcpu-ubuntu-2204

steps:
- uses: actions/checkout@v4

- name: Switch to nightly rust
run: rustup default nightly

- name: Benchmark AVX2 (nightly)
run: cargo bench --bench throughput --features 'bench-plot avx2'
- name: Benchmark
run: cargo bench --bench throughput --features bench-plot

- uses: actions/upload-artifact@v3
with:
name: benches
path: benches/throughput/*.svg
path: benches/throughput/x86_64-hybrid.svg

benchmark-arm:
name: Benchmark ARM
Expand All @@ -36,17 +48,17 @@ jobs:
- uses: actions/checkout@v4

- name: Benchmark
run: cargo bench --bench throughput --features 'bench-plot'
run: cargo bench --bench throughput --features bench-plot

- uses: actions/upload-artifact@v3
with:
name: benches
path: benches/throughput/*.svg
path: benches/throughput/aarch64.svg

commit:
name: Commit & Push
runs-on: buildjet-2vcpu-ubuntu-2204
needs: [benchmark-x86, benchmark-arm]
needs: [benchmark-x86, benchmark-x86-avx2, benchmark-arm]

permissions:
contents: write
Expand Down
34 changes: 32 additions & 2 deletions .github/workflows/build_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,44 @@ env:
CARGO_TERM_COLOR: always

jobs:
build_test:
build_test_x86:
name: Build & Test X86
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

name: Build & Test
- name: Build
run: cargo build --release

- name: Test
run: cargo test --release

build_test_x86_avx2:
name: Build & Test X86 AVX2
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Switch to nightly rust
run: rustup default nightly

- name: Build
run: cargo build --release

- name: Test
run: cargo test --release

build_test_arm:
name: Build & Test ARM
runs-on: buildjet-2vcpu-ubuntu-2204-arm

steps:
- uses: actions/checkout@v3

- name: Build
run: cargo build --release

- name: Test
run: cargo test --release
9 changes: 4 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]
name = "gxhash"
authors = ["Olivier Giniaux"]
version = "2.3.1"
version = "3.0.0"
edition = "2021"
description = "GxHash non-cryptographic algorithm"
license = "MIT"
Expand All @@ -13,10 +13,6 @@ categories = ["algorithms", "data-structures", "no-std"]
exclude = ["article/*"]

[features]
# The 256-bit state GxHash is faster for large inputs than the default 128-bit state implementation, but faster on smaller hashes.
# Please not however that the 256-bit GxHash and the 128-bit GxHash don't generate the same hashes for a same input.
# Requires AVX2 and VAES (X86).
avx2 = []
# Only relevant for throughput benchmarks
bench-csv = []
bench-md = []
Expand All @@ -39,6 +35,9 @@ seahash = "4.1.0"
metrohash = "1.0.6"
fnv = "1.0.3"

[build-dependencies]
rustc_version = "0.4.0"

[dev-dependencies.plotters]
version = "0.3.5"
default-features = false
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ GxHash is compatible with:
> Other platforms are currently not supported (there is no fallback). The behavior on these platforms is undefined.
### Hashes Stability
All generated hashes for a given version of GxHash are stable, meaning that for a given input the output hash will be the same across all supported platforms. An exception to this is the AVX2 version of GxHash (nightly).
All generated hashes for a given version of GxHash are stable, meaning that for a given input the output hash will be the same across all supported platforms.

## Benchmarks

Expand Down Expand Up @@ -74,7 +74,7 @@ GxHash is continuously benchmarked on X86 and ARM Github runners.
GxHash is a seeded hashing algorithm, meaning that depending on the seed used, it will generate completely different hashes. The default `HasherBuilder` (`GxHasherBuilder::default()`) uses seed randomization, making any `HashMap`/`HashSet` more DOS resistant, as it will make it much more difficult for attackers to be able to predict which hashes may collide without knowing the seed used. This does not mean however that it is completely DOS resistant. This has to be analyzed further.

### Multicollisions Resistance
GxHash uses a 128-bit internal state (and even 256-bit with the `avx2` feature). This makes GxHash [a widepipe construction](https://en.wikipedia.org/wiki/Merkle%E2%80%93Damg%C3%A5rd_construction#Wide_pipe_construction) when generating hashes of size 64-bit or smaller, which had amongst other properties to be inherently more resistant to multicollision attacks. See [this paper](https://www.iacr.org/archive/crypto2004/31520306/multicollisions.pdf) for more details.
GxHash uses a 128-bit internal state. This makes GxHash [a widepipe construction](https://en.wikipedia.org/wiki/Merkle%E2%80%93Damg%C3%A5rd_construction#Wide_pipe_construction) when generating hashes of size 64-bit or smaller, which had amongst other properties to be inherently more resistant to multicollision attacks. See [this paper](https://www.iacr.org/archive/crypto2004/31520306/multicollisions.pdf) for more details.

### Cryptographic Properties
GxHash is a non-cryptographic hashing algorithm, thus it is not recommended to use it as a cryptographic algorithm (it is not a replacement for SHA). It has not been assessed if GxHash is preimage resistant and how difficult it is to be reversed.
Expand Down Expand Up @@ -103,4 +103,4 @@ Publication:
[PDF](https://github.com/ogxd/gxhash-rust/blob/main/article/article.pdf)

Cite this publication / algorithm:
[![DOI](https://zenodo.org/badge/690754256.svg)](https://zenodo.org/badge/latestdoi/690754256)
[![DOI](https://zenodo.org/badge/690754256.svg)](https://zenodo.org/badge/latestdoi/690754256)
70 changes: 38 additions & 32 deletions benches/throughput/aarch64.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion benches/throughput/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ fn main() {
};

// GxHash
let gxhash_name = if cfg!(feature = "avx2") { "gxhash-avx2" } else { "gxhash" };
let gxhash_name = if cfg!(hybrid) { "gxhash-hybrid" } else { "gxhash" };
benchmark(processor.as_mut(), slice, gxhash_name, |data: &[u8], seed: i64| -> u64 {
gxhash64(data, seed)
});
Expand Down
6 changes: 3 additions & 3 deletions benches/throughput/result_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ impl ResultProcessor for OutputPlot {

fn finish(&self) {
let mut arch = std::env::consts::ARCH.to_string();
if cfg!(feature = "avx2") {
arch += "-avx2";
if cfg!(hybrid) {
arch += "-hybrid";
}
let file_name = format!("benches/throughput/{}.svg", arch);

Expand Down Expand Up @@ -176,6 +176,6 @@ impl ResultProcessor for OutputPlot {
// To avoid the IO failure being ignored silently, we manually call the present function
canvas.present().expect("Unable to write result to file, please make sure 'plotters-doc-data' dir exists under current dir");

println!("Finished");
println!("Finished: '{}'", file_name);
}
}
Loading

0 comments on commit 6c555a9

Please sign in to comment.