├── .gitattributes ├── .github ├── dependabot.yml └── workflows │ ├── build.yml │ ├── codeql-analysis.yml │ ├── gradle-wrapper-validation.yml │ └── sonarqube-analysis.yml ├── .gitignore ├── .gitmodules ├── .palantir └── revapi.yml ├── LICENSE ├── README.md ├── build.gradle ├── doc ├── hyperloglog-estimation-error.md ├── images │ └── logo │ │ ├── hash4j-logo-small.png │ │ ├── hash4j-logo.png │ │ └── hash4j-logo.svg └── ultraloglog-estimation-error.md ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── licenses ├── APACHE_2_0_DYNATRACE.txt ├── APACHE_2_0_GUAVA.txt ├── APACHE_2_0_XXH.txt ├── BOOST_EXPONENTIAL_RANDOM_GENERATION.txt ├── CREATIVE_COMMONS_SPLITMIX64.txt ├── MIT_ANCHOR_HASH.txt ├── MIT_APACHE_2_0_FARMHASH.txt ├── MIT_IMOHASH.txt ├── MIT_KOMIHASH.txt └── ZLIB_POLYMURHASH.txt ├── python ├── benchmark_evaluation.py └── estimation_error_evaluation.py ├── reference-implementations ├── build.sh ├── calculate_checksums.cpp ├── farmhash_na │ ├── farmhash_na_checksum_config.cpp │ └── farmhash_na_checksum_config.hpp ├── farmhash_uo │ ├── farmhash_uo_checksum_config.cpp │ └── farmhash_uo_checksum_config.hpp ├── imohash_1_0_2 │ ├── go.mod │ ├── go.sum │ └── test.go ├── komihash_4_3 │ ├── komihash_4_3_checksum_config.cpp │ └── komihash_4_3_checksum_config.hpp ├── komihash_4_7 │ ├── komihash_4_7_checksum_config.cpp │ └── komihash_4_7_checksum_config.hpp ├── komihash_5_0 │ ├── komihash_5_0_checksum_config.cpp │ └── komihash_5_0_checksum_config.hpp ├── komihash_5_10 │ ├── komihash_5_10_checksum_config.cpp │ └── komihash_5_10_checksum_config.hpp ├── komihash_5_27 │ ├── komihash_5_27_checksum_config.cpp │ └── komihash_5_27_checksum_config.hpp ├── murmur3_128 │ ├── murmur3_128_checksum_config.cpp │ └── murmur3_128_checksum_config.hpp ├── murmur3_32 │ ├── murmur3_32_checksum_config.cpp │ └── murmur3_32_checksum_config.hpp ├── polymur-hash_2_0 │ ├── polymur-hash_2_0_checksum_config.cpp │ └── polymur-hash_2_0_checksum_config.hpp ├── wyhash_final_3 │ ├── wyhash_final_3_checksum_config.cpp │ └── wyhash_final_3_checksum_config.hpp ├── wyhash_final_4 │ ├── wyhash_final_4_checksum_config.cpp │ └── wyhash_final_4_checksum_config.hpp ├── xxh3 │ ├── xxh3_checksum_config.cpp │ └── xxh3_checksum_config.hpp └── xxh3_128 │ ├── xxh3_128_checksum_config.cpp │ └── xxh3_128_checksum_config.hpp ├── requirements.txt ├── settings.gradle ├── src ├── jmh │ └── java │ │ └── com │ │ └── dynatrace │ │ └── hash4j │ │ ├── consistent │ │ ├── ConsistentJumpBackBucketHasherPerformanceTest.java │ │ ├── ConsistentJumpBucketHasherPerformanceTest.java │ │ ├── ImprovedConsistentWeightedSamplingPerformanceTest.java │ │ ├── ModuloAssignmentPerformanceTest.java │ │ ├── RandomAssignmentPerformanceTest.java │ │ └── RandomNumberPerformanceTest.java │ │ ├── distinctcount │ │ ├── HyperLogLogPerformanceTest.java │ │ └── UltraLogLogPerformanceTest.java │ │ ├── hashing │ │ ├── AbstactHasher128PerformanceTest.java │ │ ├── AbstactHasher32PerformanceTest.java │ │ ├── AbstactHasher64PerformanceTest.java │ │ ├── AbstractGuava128BitPerformanceTest.java │ │ ├── AbstractGuava32BitPerformanceTest.java │ │ ├── AbstractGuava64BitPerformanceTest.java │ │ ├── AbstractPerformanceTest.java │ │ ├── AbstractZeroAllocationHashing128BitPerformanceTest.java │ │ ├── AbstractZeroAllocationHashing64BitPerformanceTest.java │ │ ├── FarmHashNaGuavaPerformanceTest.java │ │ ├── FarmHashNaPerformanceTest.java │ │ ├── FarmHashNaZeroAllocationHashingPerformanceTest.java │ │ ├── FarmHashUoPerformanceTest.java │ │ ├── FarmHashUoZeroAllocationHashingPerformanceTest.java │ │ ├── Komihash4_3PerformanceTest.java │ │ ├── Komihash5_0PerformanceTest.java │ │ ├── Murmur3_128GreenrobotEssentialsPerformanceTest.java │ │ ├── Murmur3_128GuavaPerformanceTest.java │ │ ├── Murmur3_128PerformanceTest.java │ │ ├── Murmur3_128ZeroAllocationHashingPerformanceTest.java │ │ ├── Murmur3_32GreenrobotEssentialsPerformanceTest.java │ │ ├── Murmur3_32GuavaPerformanceTest.java │ │ ├── Murmur3_32PerformanceTest.java │ │ ├── PolymurHash2_0PerformanceTest.java │ │ ├── UnorderedHashTest.java │ │ ├── WyhashFinal3PerformanceTest.java │ │ ├── WyhashFinal4PerformanceTest.java │ │ ├── XXH3_128PerformanceTest.java │ │ ├── XXH3_128ZeroAllocationHashingPerformanceTest.java │ │ ├── XXH3_64PerformanceTest.java │ │ ├── XXH3_64ZeroAllocationHashingPerformanceTest.java │ │ └── package-info.java │ │ ├── random │ │ └── RandomPerformanceTest.java │ │ └── similarity │ │ ├── FastSimHash_v1PerformanceTest.java │ │ ├── MinHash_v1PerformanceTest.java │ │ ├── SimHash_v1PerformanceTest.java │ │ ├── SimilarityHashingPerformanceTest.java │ │ ├── SuperMinHash_v1PerformanceTest.java │ │ ├── SuperMinHash_v1aPerformanceTest.java │ │ └── SuperMinHash_v1bPerformanceTest.java ├── main │ ├── java │ │ ├── com │ │ │ └── dynatrace │ │ │ │ └── hash4j │ │ │ │ ├── consistent │ │ │ │ ├── ConsistentBucketHasher.java │ │ │ │ ├── ConsistentBucketSetHasher.java │ │ │ │ ├── ConsistentHashing.java │ │ │ │ ├── ConsistentHashingUtil.java │ │ │ │ ├── ConsistentJumpBackAnchorBucketSetHasher.java │ │ │ │ ├── ConsistentJumpBackBucketHasher.java │ │ │ │ ├── ConsistentJumpBucketHasher.java │ │ │ │ ├── ImprovedConsistentWeightedSampling.java │ │ │ │ └── package-info.java │ │ │ │ ├── distinctcount │ │ │ │ ├── DistinctCountUtil.java │ │ │ │ ├── DistinctCounter.java │ │ │ │ ├── HyperLogLog.java │ │ │ │ ├── MartingaleEstimator.java │ │ │ │ ├── StateChangeObserver.java │ │ │ │ ├── UltraLogLog.java │ │ │ │ └── package-info.java │ │ │ │ ├── file │ │ │ │ ├── AbstractFileHasher128.java │ │ │ │ ├── FileHasher128.java │ │ │ │ ├── FileHashing.java │ │ │ │ ├── Imohash1_0_2.java │ │ │ │ └── package-info.java │ │ │ │ ├── hashing │ │ │ │ ├── AbstractFarmHash.java │ │ │ │ ├── AbstractHashStream.java │ │ │ │ ├── AbstractHashStream128.java │ │ │ │ ├── AbstractHashStream32.java │ │ │ │ ├── AbstractHashStream64.java │ │ │ │ ├── AbstractHasher128.java │ │ │ │ ├── AbstractHasher32.java │ │ │ │ ├── AbstractHasher64.java │ │ │ │ ├── AbstractKomihash.java │ │ │ │ ├── AbstractWyhashFinal.java │ │ │ │ ├── FarmHashNa.java │ │ │ │ ├── FarmHashUo.java │ │ │ │ ├── HashFunnel.java │ │ │ │ ├── HashSink.java │ │ │ │ ├── HashStream.java │ │ │ │ ├── HashStream128.java │ │ │ │ ├── HashStream32.java │ │ │ │ ├── HashStream64.java │ │ │ │ ├── HashValue128.java │ │ │ │ ├── HashValues.java │ │ │ │ ├── Hasher.java │ │ │ │ ├── Hasher128.java │ │ │ │ ├── Hasher32.java │ │ │ │ ├── Hasher64.java │ │ │ │ ├── Hashing.java │ │ │ │ ├── Komihash4_3.java │ │ │ │ ├── Komihash5_0.java │ │ │ │ ├── Murmur3_128.java │ │ │ │ ├── Murmur3_32.java │ │ │ │ ├── PolymurHash2_0.java │ │ │ │ ├── WyhashFinal3.java │ │ │ │ ├── WyhashFinal4.java │ │ │ │ ├── XXH3Base.java │ │ │ │ ├── XXH3_128.java │ │ │ │ ├── XXH3_64.java │ │ │ │ └── package-info.java │ │ │ │ ├── internal │ │ │ │ ├── ArraySizeUtil.java │ │ │ │ ├── ByteArrayUtil.java │ │ │ │ ├── EmptyArray.java │ │ │ │ ├── Preconditions.java │ │ │ │ ├── UnsignedMultiplyUtil.java │ │ │ │ └── package-info.java │ │ │ │ ├── random │ │ │ │ ├── AbstractPseudoRandomGenerator.java │ │ │ │ ├── PermutationGenerator.java │ │ │ │ ├── PseudoRandomGenerator.java │ │ │ │ ├── PseudoRandomGeneratorProvider.java │ │ │ │ ├── RandomExponentialUtil.java │ │ │ │ ├── SplitMix64V1.java │ │ │ │ └── package-info.java │ │ │ │ ├── similarity │ │ │ │ ├── AbstractSimilarityHashPolicy.java │ │ │ │ ├── DistinctElementHashProvider.java │ │ │ │ ├── ElementHashProvider.java │ │ │ │ ├── FastSimHashPolicy_v1.java │ │ │ │ ├── FastSimHashVersion.java │ │ │ │ ├── MinHashPolicy_v1.java │ │ │ │ ├── MinHashVersion.java │ │ │ │ ├── SimHashPolicy_v1.java │ │ │ │ ├── SimHashVersion.java │ │ │ │ ├── SimilarityHashPolicy.java │ │ │ │ ├── SimilarityHasher.java │ │ │ │ ├── SimilarityHashing.java │ │ │ │ ├── SuperMinHashPolicy_v1.java │ │ │ │ ├── SuperMinHashPolicy_v1a.java │ │ │ │ ├── SuperMinHashPolicy_v1b.java │ │ │ │ ├── SuperMinHashVersion.java │ │ │ │ └── package-info.java │ │ │ │ └── util │ │ │ │ ├── PackedArray.java │ │ │ │ └── package-info.java │ │ └── module-info.java │ └── java21 │ │ └── com │ │ └── dynatrace │ │ └── hash4j │ │ └── internal │ │ └── UnsignedMultiplyUtil.java └── test │ ├── java │ └── com │ │ └── dynatrace │ │ └── hash4j │ │ ├── consistent │ │ ├── AbstractConsistentBucketHasherTest.java │ │ ├── AbstractConsistentBucketSetHasherTest.java │ │ ├── ConsistentHashingDemo.java │ │ ├── ConsistentHashingUtilTest.java │ │ ├── ConsistentJumpBackAnchorBucketSetHasherTest.java │ │ ├── ConsistentJumpBackBucketHasherTest.java │ │ ├── ConsistentJumpBucketHasherTest.java │ │ └── ImprovedConsistentWeightedSamplingTest.java │ │ ├── distinctcount │ │ ├── BigInt.java │ │ ├── BigIntTest.java │ │ ├── ConversionDemo.java │ │ ├── DistinctCountUtilTest.java │ │ ├── DistinctCounterTest.java │ │ ├── EstimationErrorSimulationUtil.java │ │ ├── HyperLogLogDemo.java │ │ ├── HyperLogLogEstimationErrorSimulation.java │ │ ├── HyperLogLogTest.java │ │ ├── MartingaleEstimatorTest.java │ │ ├── TestUtils.java │ │ ├── TestUtilsTest.java │ │ ├── UltraLogLogDemo.java │ │ ├── UltraLogLogEstimationErrorSimulation.java │ │ └── UltraLogLogTest.java │ │ ├── file │ │ ├── AbstractFileHasher128Test.java │ │ ├── FileHashingDemo.java │ │ └── Imohash1_0_2Test.java │ │ ├── hashing │ │ ├── AbstractHashSinkPutUnorderedIterableTest.java │ │ ├── AbstractHashStream128Test.java │ │ ├── AbstractHashStream32Test.java │ │ ├── AbstractHashStream64Test.java │ │ ├── AbstractHashStreamCompatibilityTest.java │ │ ├── AbstractHashStreamTest.java │ │ ├── AbstractHasher128Test.java │ │ ├── AbstractHasher32Test.java │ │ ├── AbstractHasher64Test.java │ │ ├── AbstractHasherTest.java │ │ ├── CrossCheckTest.java │ │ ├── FarmHashNaTest.java │ │ ├── FarmHashUoTest.java │ │ ├── HashValue128Test.java │ │ ├── HashValuesTest.java │ │ ├── HashingDemo.java │ │ ├── Komihash4_3Test.java │ │ ├── Komihash5_0Test.java │ │ ├── Murmur3_128Test.java │ │ ├── Murmur3_32Test.java │ │ ├── PolymurHash2_0Test.java │ │ ├── TestHashStream.java │ │ ├── TestUtils.java │ │ ├── WyhashFinal3Test.java │ │ ├── WyhashFinal4Test.java │ │ ├── XXH3_128Test.java │ │ └── XXH3_64Test.java │ │ ├── internal │ │ ├── ArraySizeUtilTest.java │ │ ├── PreconditionsTest.java │ │ └── UnsignedMultiplyUtilTest.java │ │ ├── random │ │ ├── AbstractPseudoRandomGeneratorProviderTest.java │ │ ├── AbstractPseudoRandomGeneratorTest.java │ │ ├── PermutationGeneratorTest.java │ │ ├── PseudoRandomGeneratorProviderForTesting.java │ │ ├── RandomExponentialUtilTest.java │ │ ├── SplitMix64_v1ProviderTest.java │ │ └── SplitMix64_v1Test.java │ │ ├── similarity │ │ ├── AbstractMinHashPolicyTest.java │ │ ├── AbstractSimHashPolicyTest.java │ │ ├── AbstractSimilarityHasherPolicyTest.java │ │ ├── AbstractSuperMinHashPolicyTest.java │ │ ├── DistinctElementHashProviderTest.java │ │ ├── ElementHashProviderTest.java │ │ ├── FastSimHashPolicy_v1Test.java │ │ ├── MinHashPolicy_v1Test.java │ │ ├── MinHashVersionTest.java │ │ ├── SimHashPolicy_v1Test.java │ │ ├── SimilarityHashingDemo.java │ │ ├── SimilarityHashingTest.java │ │ ├── SuperMinHashPolicy_v1Test.java │ │ ├── SuperMinHashPolicy_v1aTest.java │ │ ├── SuperMinHashPolicy_v1bTest.java │ │ └── SuperMinHashVersionTest.java │ │ ├── testutils │ │ ├── TestUtils.java │ │ └── TestUtilsTest.java │ │ └── util │ │ └── PackedArrayTest.java │ ├── java21 │ └── com │ │ └── dynatrace │ │ └── hash4j │ │ └── internal │ │ └── UnsignedMultiplyUtilReferenceTest.java │ └── resources │ ├── FarmHash NA.txt │ ├── FarmHash UO.txt │ ├── Komihash 4.3.txt │ ├── Komihash 4.7.txt │ ├── Komihash 5.0.txt │ ├── Komihash 5.10.txt │ ├── Komihash 5.27.txt │ ├── Murmur3 128.txt │ ├── Murmur3 32.txt │ ├── PolymurHash 2.0.txt │ ├── Wyhash final 3.txt │ ├── Wyhash final 4.txt │ ├── XXH3.txt │ ├── XXH3_128.txt │ └── junit-platform.properties └── test-results ├── hyperloglog-estimation-error-p03.csv ├── hyperloglog-estimation-error-p03.png ├── hyperloglog-estimation-error-p04.csv ├── hyperloglog-estimation-error-p04.png ├── hyperloglog-estimation-error-p05.csv ├── hyperloglog-estimation-error-p05.png ├── hyperloglog-estimation-error-p06.csv ├── hyperloglog-estimation-error-p06.png ├── hyperloglog-estimation-error-p07.csv ├── hyperloglog-estimation-error-p07.png ├── hyperloglog-estimation-error-p08.csv ├── hyperloglog-estimation-error-p08.png ├── hyperloglog-estimation-error-p09.csv ├── hyperloglog-estimation-error-p09.png ├── hyperloglog-estimation-error-p10.csv ├── hyperloglog-estimation-error-p10.png ├── hyperloglog-estimation-error-p11.csv ├── hyperloglog-estimation-error-p11.png ├── hyperloglog-estimation-error-p12.csv ├── hyperloglog-estimation-error-p12.png ├── hyperloglog-estimation-error-p13.csv ├── hyperloglog-estimation-error-p13.png ├── hyperloglog-estimation-error-p14.csv ├── hyperloglog-estimation-error-p14.png ├── hyperloglog-estimation-error-p15.csv ├── hyperloglog-estimation-error-p15.png ├── hyperloglog-estimation-error-p16.csv ├── hyperloglog-estimation-error-p16.png ├── ultraloglog-estimation-error-p03.csv ├── ultraloglog-estimation-error-p03.png ├── ultraloglog-estimation-error-p04.csv ├── ultraloglog-estimation-error-p04.png ├── ultraloglog-estimation-error-p05.csv ├── ultraloglog-estimation-error-p05.png ├── ultraloglog-estimation-error-p06.csv ├── ultraloglog-estimation-error-p06.png ├── ultraloglog-estimation-error-p07.csv ├── ultraloglog-estimation-error-p07.png ├── ultraloglog-estimation-error-p08.csv ├── ultraloglog-estimation-error-p08.png ├── ultraloglog-estimation-error-p09.csv ├── ultraloglog-estimation-error-p09.png ├── ultraloglog-estimation-error-p10.csv ├── ultraloglog-estimation-error-p10.png ├── ultraloglog-estimation-error-p11.csv ├── ultraloglog-estimation-error-p11.png ├── ultraloglog-estimation-error-p12.csv ├── ultraloglog-estimation-error-p12.png ├── ultraloglog-estimation-error-p13.csv ├── ultraloglog-estimation-error-p13.png ├── ultraloglog-estimation-error-p14.csv ├── ultraloglog-estimation-error-p14.png ├── ultraloglog-estimation-error-p15.csv ├── ultraloglog-estimation-error-p15.png ├── ultraloglog-estimation-error-p16.csv └── ultraloglog-estimation-error-p16.png /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | *.java text eol=lf 3 | *.hpp text eol=lf 4 | *.cpp text eol=lf 5 | *.txt text eol=lf 6 | *.py text eol=lf 7 | *.md text eol=lf 8 | *.csv text 9 | gradlew.bat text eol=crlf 10 | gradlew text eol=lf 11 | *.gradle eol=lf 12 | *.sh text eol=lf 13 | *.yml text eol=lf 14 | *.jar binary -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | registries: 3 | gradle-plugin-portal: 4 | type: maven-repository 5 | url: https://plugins.gradle.org/m2 6 | username: dummy # Required by dependabot 7 | password: dummy # Required by dependabot 8 | updates: 9 | - package-ecosystem: "github-actions" 10 | directory: "/" 11 | schedule: 12 | interval: "daily" 13 | 14 | - package-ecosystem: "gradle" 15 | directory: "/" 16 | registries: 17 | - gradle-plugin-portal 18 | schedule: 19 | interval: "daily" 20 | open-pull-requests-limit: 10 21 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | types: [opened, synchronize, reopened] 8 | jobs: 9 | build: 10 | name: Build Java (${{ matrix.os }}) 11 | runs-on: ${{ matrix.os }} 12 | strategy: 13 | matrix: 14 | os: [ 'ubuntu-latest', 'windows-latest', 'macos-latest' ] 15 | steps: 16 | - uses: actions/checkout@v4 17 | with: 18 | fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis 19 | - name: Set up Java 20 | uses: actions/setup-java@v4 21 | with: 22 | java-version: | 23 | 11 24 | 21 25 | distribution: 'temurin' 26 | - name: Set up Python 27 | uses: actions/setup-python@v5 28 | with: 29 | python-version: '3.12' 30 | - name: Install Python dependencies 31 | run: | 32 | python -m pip install --upgrade pip 33 | pip install -r requirements.txt 34 | - name: Cache Gradle packages 35 | uses: actions/cache@v4 36 | with: 37 | path: ~/.gradle/caches 38 | key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} 39 | restore-keys: ${{ runner.os }}-gradle 40 | - name: Build 41 | run: ./gradlew build 42 | -------------------------------------------------------------------------------- /.github/workflows/gradle-wrapper-validation.yml: -------------------------------------------------------------------------------- 1 | name: "Validate Gradle Wrapper" 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | validation: 6 | name: "Validation" 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v4 10 | - uses: gradle/actions/wrapper-validation@v4 11 | -------------------------------------------------------------------------------- /.github/workflows/sonarqube-analysis.yml: -------------------------------------------------------------------------------- 1 | name: "SonarQube" 2 | on: 3 | push: 4 | branches: 5 | - main 6 | jobs: 7 | build: 8 | name: Build 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v4 12 | with: 13 | fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis 14 | - name: Set up Java 15 | uses: actions/setup-java@v4 16 | with: 17 | java-version: | 18 | 11 19 | 21 20 | distribution: 'temurin' 21 | - name: Cache SonarCloud packages 22 | uses: actions/cache@v4 23 | with: 24 | path: ~/.sonar/cache 25 | key: ${{ runner.os }}-sonar 26 | restore-keys: ${{ runner.os }}-sonar 27 | - name: Cache Gradle packages 28 | uses: actions/cache@v4 29 | with: 30 | path: ~/.gradle/caches 31 | key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} 32 | restore-keys: ${{ runner.os }}-gradle 33 | - name: Build and analyze 34 | env: 35 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any 36 | SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} 37 | run: ./gradlew build sonarqube --info 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # folders 2 | /.gradle/ 3 | /build/ 4 | /benchmark-results/ 5 | /bin/ 6 | /.idea/ 7 | /.vs/ 8 | /.classpath 9 | /.project 10 | /.settings/ 11 | /.venv/ 12 | /test-results/hyperloglog-estimation-error-p??-maximum-likelihood.png 13 | /test-results/ultraloglog-estimation-error-p??-maximum-likelihood.png 14 | /test-results/ultraloglog-estimation-error-p??-optimal-FGRA.png 15 | /test-results/ultraloglog-estimation-error-p??-default.png 16 | /test-results/ultraloglog-estimation-error-p??-martingale.png 17 | /test-results/hyperloglog-estimation-error-p??-default.png 18 | /test-results/hyperloglog-estimation-error-p??-martingale.png 19 | /test-results/hyperloglog-estimation-error-p??-small-range-corrected-raw.png 20 | /test-results/hyperloglog-estimation-error-p??-corrected-raw.png 21 | /reference-implementations/calculate_checksums 22 | /reference-implementations/farmhash.o 23 | /reference-implementations/farmhash_na_checksum_config.o 24 | /reference-implementations/farmhash_uo_checksum_config.o 25 | /reference-implementations/farmna.a 26 | /reference-implementations/farmuo.a 27 | /extra-configuration.gradle -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "reference-implementations/komihash_4_3/komihash"] 2 | path = reference-implementations/komihash_4_3/komihash 3 | url = https://github.com/avaneev/komihash.git 4 | [submodule "reference-implementations/komihash_4_7/komihash"] 5 | path = reference-implementations/komihash_4_7/komihash 6 | url = https://github.com/avaneev/komihash.git 7 | [submodule "reference-implementations/wyhash_final_3/wyhash"] 8 | path = reference-implementations/wyhash_final_3/wyhash 9 | url = https://github.com/wangyi-fudan/wyhash.git 10 | [submodule "reference-implementations/murmur3_128/smhasher"] 11 | path = reference-implementations/murmur3_128/smhasher 12 | url = https://github.com/aappleby/smhasher 13 | [submodule "reference-implementations/murmur3_32/smhasher"] 14 | path = reference-implementations/murmur3_32/smhasher 15 | url = https://github.com/aappleby/smhasher 16 | [submodule "reference-implementations/xxh3/xxHash"] 17 | path = reference-implementations/xxh3/xxHash 18 | url = https://github.com/Cyan4973/xxHash.git 19 | [submodule "reference-implementations/farmhash_uo/farmhash"] 20 | path = reference-implementations/farmhash_uo/farmhash 21 | url = https://github.com/google/farmhash.git 22 | [submodule "reference-implementations/farmhash_na/farmhash"] 23 | path = reference-implementations/farmhash_na/farmhash 24 | url = https://github.com/google/farmhash.git 25 | [submodule "reference-implementations/wyhash_final_4/wyhash"] 26 | path = reference-implementations/wyhash_final_4/wyhash 27 | url = https://github.com/wangyi-fudan/wyhash.git 28 | [submodule "reference-implementations/komihash_5_0/komihash"] 29 | path = reference-implementations/komihash_5_0/komihash 30 | url = https://github.com/avaneev/komihash.git 31 | [submodule "reference-implementations/polymur-hash_2_0/polymur-hash"] 32 | path = reference-implementations/polymur-hash_2_0/polymur-hash 33 | url = https://github.com/orlp/polymur-hash.git 34 | [submodule "reference-implementations/komihash_5_10/komihash"] 35 | path = reference-implementations/komihash_5_10/komihash 36 | url = https://github.com/avaneev/komihash.git 37 | [submodule "reference-implementations/xxh3_128/xxHash"] 38 | path = reference-implementations/xxh3_128/xxHash 39 | url = https://github.com/Cyan4973/xxHash.git 40 | [submodule "reference-implementations/komihash_5_27/komihash"] 41 | path = reference-implementations/komihash_5_27/komihash 42 | url = https://github.com/avaneev/komihash.git 43 | -------------------------------------------------------------------------------- /doc/hyperloglog-estimation-error.md: -------------------------------------------------------------------------------- 1 | ### HyperLogLog estimation error 2 | 3 | The state of an HyperLogLog sketch with precision parameter $p$ requires $0.75 \cdot m = 0.75 \cdot 2^p$ bytes where $m$ denotes the number of registers. 4 | The expected relative standard error is approximately given by $\frac{1.039}{\sqrt{m}}$,$\frac{1.037}{\sqrt{m}}$, 5 | and $\frac{0.833}{\sqrt{m}}$ for the default, the maximum-likelihood (ML), and the martingale estimator, respectively. 6 | This is a good approximation for all $p\geq 6$ and large distinct counts. 7 | However, the error is significantly smaller for distinct counts that are in the order of $m$ or smaller. 8 | The bias is always much smaller than the root-mean-square error (rmse) and can therefore be neglected. 9 | The following charts show the empirically determined relative error as a function of the true distinct count for various precision parameters $p$ based on 100k simulation runs. Distinct counts up to 1M were simulated by generating random values as hash values. For distinct counts above 1M, a different technique is used by randomly generating only hash values at distinct counts that can actually change the state of the data structure. 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /doc/images/logo/hash4j-logo-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/doc/images/logo/hash4j-logo-small.png -------------------------------------------------------------------------------- /doc/images/logo/hash4j-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/doc/images/logo/hash4j-logo.png -------------------------------------------------------------------------------- /doc/images/logo/hash4j-logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /doc/ultraloglog-estimation-error.md: -------------------------------------------------------------------------------- 1 | ### UltraLogLog estimation error 2 | 3 | The state of an UltraLogLog sketch with precision parameter $p$ requires $m = 2^p$ bytes where $m$ denotes the number of registers. 4 | The expected relative standard error is approximately given by $\frac{0.782}{\sqrt{m}}$, $\frac{0.761}{\sqrt{m}}$, 5 | and $\frac{0.658}{\sqrt{m}}$ for the default, the maximum-likelihood (ML), and the martingale estimator, respectively. 6 | This is a good approximation for all $p\geq 6$ and large distinct counts. 7 | However, the error is significantly smaller for distinct counts that are in the order of $m$ or smaller. 8 | The bias is always much smaller than the root-mean-square error (rmse) and can therefore be neglected. 9 | The following charts show the empirically determined relative error as a function of the true distinct count for various precision parameters $p$ based on 100k simulation runs. Distinct counts up to 1M were simulated by generating random values as hash values. For distinct counts above 1M, a different technique is used by randomly generating only hash values at distinct counts that can actually change the state of the data structure. 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx8g 2 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /licenses/APACHE_2_0_DYNATRACE.txt: -------------------------------------------------------------------------------- 1 | Copyright $YEAR Dynatrace LLC 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. -------------------------------------------------------------------------------- /licenses/APACHE_2_0_GUAVA.txt: -------------------------------------------------------------------------------- 1 | This file includes a modified version of the consistentHash method 2 | (see https://github.com/google/guava/blob/0a17f4a429323589396c38d8ce75ca058faa6c64/guava/src/com/google/common/hash/Hashing.java#L559) 3 | from Google's Guava library which was published with following copyright notes and under the 4 | license given below: 5 | 6 | 7 | Copyright (C) 2011 The Guava Authors 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 10 | in compliance with the License. You may obtain a copy of the License at 11 | 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | 14 | Unless required by applicable law or agreed to in writing, software distributed under the License 15 | is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 16 | or implied. See the License for the specific language governing permissions and limitations under 17 | the License. -------------------------------------------------------------------------------- /licenses/APACHE_2_0_XXH.txt: -------------------------------------------------------------------------------- 1 | This implementation was derived from 2 | 3 | https://github.com/OpenHFT/Zero-Allocation-Hashing/blob/zero-allocation-hashing-0.16/src/main/java/net/openhft/hashing/XXH3.java 4 | 5 | which was published under the license below: 6 | 7 | Copyright 2015 Higher Frequency Trading http://www.higherfrequencytrading.com 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); 10 | you may not use this file except in compliance with the License. 11 | You may obtain a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, 17 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | See the License for the specific language governing permissions and 19 | limitations under the License. -------------------------------------------------------------------------------- /licenses/BOOST_EXPONENTIAL_RANDOM_GENERATION.txt: -------------------------------------------------------------------------------- 1 | This file includes a Java port of an algorithm for the generation of 2 | exponentially distributed random values which is based on 3 | 4 | https://github.com/boostorg/random/blob/18999b33d9a64b574435668541a37ddefb2851df/include/boost/random/exponential_distribution.hpp 5 | 6 | and which was published with following copyright notes and under the 7 | license given below: 8 | 9 | 10 | Copyright Jens Maurer 2000-2001 11 | Copyright Steven Watanabe 2011 12 | Copyright Jason Rhinelander 2016 13 | Distributed under the Boost Software License, Version 1.0. (See 14 | accompanying file LICENSE_1_0.txt or copy at 15 | http://www.boost.org/LICENSE_1_0.txt) 16 | 17 | See http://www.boost.org for most recent version including documentation. 18 | 19 | 20 | Boost Software License - Version 1.0 - August 17th, 2003 21 | 22 | Permission is hereby granted, free of charge, to any person or organization 23 | obtaining a copy of the software and accompanying documentation covered by 24 | this license (the "Software") to use, reproduce, display, distribute, 25 | execute, and transmit the Software, and to prepare derivative works of the 26 | Software, and to permit third-parties to whom the Software is furnished to 27 | do so, all subject to the following: 28 | 29 | The copyright notices in the Software and this entire statement, including 30 | the above license grant, this restriction and the following disclaimer, 31 | must be included in all copies of the Software, in whole or in part, and 32 | all derivative works of the Software, unless such copies or derivative 33 | works are solely in the form of machine-executable object code generated by 34 | a source language processor. 35 | 36 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 37 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 38 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 39 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 40 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 41 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 42 | DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /licenses/CREATIVE_COMMONS_SPLITMIX64.txt: -------------------------------------------------------------------------------- 1 | The implementation in this file is based on the implementation published 2 | at https://prng.di.unimi.it/splitmix64.c under the following license: 3 | 4 | Written in 2015 by Sebastiano Vigna (vigna@acm.org) 5 | 6 | To the extent possible under law, the author has dedicated all copyright 7 | and related and neighboring rights to this software to the public domain 8 | worldwide. This software is distributed without any warranty. 9 | 10 | See . -------------------------------------------------------------------------------- /licenses/MIT_ANCHOR_HASH.txt: -------------------------------------------------------------------------------- 1 | The implementation was partially derived from 2 | 3 | https://github.com/anchorhash/cpp-anchorhash 4 | 5 | which was published under the following license: 6 | 7 | 8 | MIT License 9 | 10 | Copyright (c) 2020 anchorhash 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy 13 | of this software and associated documentation files (the "Software"), to deal 14 | in the Software without restriction, including without limitation the rights 15 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | copies of the Software, and to permit persons to whom the Software is 17 | furnished to do so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in all 20 | copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. -------------------------------------------------------------------------------- /licenses/MIT_APACHE_2_0_FARMHASH.txt: -------------------------------------------------------------------------------- 1 | This file includes a Java port of the FarmHash algorithm originally published 2 | at https://github.com/google/farmhash under the following license: 3 | 4 | Copyright (c) 2014 Google, Inc. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | 24 | 25 | Parts of the implementation in this file have also been derived from Guava's 26 | FarmHash implementation available at 27 | https://github.com/google/guava/blob/f491b8922f9dc8003ffdf0cbde110b76bcec4b6e/guava/src/com/google/common/hash/FarmHashFingerprint64.java 28 | which was published under the following license: 29 | 30 | Copyright (C) 2015 The Guava Authors 31 | 32 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except 33 | in compliance with the License. You may obtain a copy of the License at 34 | 35 | http://www.apache.org/licenses/LICENSE-2.0 36 | 37 | Unless required by applicable law or agreed to in writing, software distributed under the License 38 | is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 39 | or implied. See the License for the specific language governing permissions and limitations under 40 | the License. -------------------------------------------------------------------------------- /licenses/MIT_IMOHASH.txt: -------------------------------------------------------------------------------- 1 | This file includes a Java port of the Imohash algorithm originally published 2 | at https://github.com/kalafut/imohash under the following license: 3 | 4 | The MIT License (MIT) 5 | 6 | Copyright (c) 2015 Jim Kalafut 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. -------------------------------------------------------------------------------- /licenses/MIT_KOMIHASH.txt: -------------------------------------------------------------------------------- 1 | This file includes a Java port of the Komihash algorithm originally published 2 | at https://github.com/avaneev/komihash under the following license: 3 | 4 | MIT License 5 | 6 | Copyright (c) 2021-2023 Aleksey Vaneev 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. -------------------------------------------------------------------------------- /licenses/ZLIB_POLYMURHASH.txt: -------------------------------------------------------------------------------- 1 | This file includes a Java port of the PolymurHash algorithm originally published 2 | at https://github.com/orlp/polymur-hash under the following license: 3 | 4 | Copyright (c) 2023 Orson Peters 5 | 6 | This software is provided 'as-is', without any express or implied warranty. In 7 | no event will the authors be held liable for any damages arising from the use of 8 | this software. 9 | 10 | Permission is granted to anyone to use this software for any purpose, including 11 | commercial applications, and to alter it and redistribute it freely, subject to 12 | the following restrictions: 13 | 14 | 1. The origin of this software must not be misrepresented; you must not claim 15 | that you wrote the original software. If you use this software in a product, 16 | an acknowledgment in the product documentation would be appreciated but is 17 | not required. 18 | 19 | 2. Altered source versions must be plainly marked as such, and must not be 20 | misrepresented as being the original software. 21 | 22 | 3. This notice may not be removed or altered from any source distribution. -------------------------------------------------------------------------------- /reference-implementations/build.sh: -------------------------------------------------------------------------------- 1 | g++ -c farmhash_uo/farmhash/src/farmhash.cc farmhash_uo/farmhash_uo_checksum_config.cpp 2 | ar rvs farmuo.a farmhash.o farmhash_uo_checksum_config.o 3 | g++ -c farmhash_na/farmhash/src/farmhash.cc farmhash_na/farmhash_na_checksum_config.cpp 4 | ar rvs farmna.a farmhash.o farmhash_na_checksum_config.o 5 | g++ \ 6 | calculate_checksums.cpp \ 7 | polymur-hash_2_0/polymur-hash_2_0_checksum_config.cpp \ 8 | wyhash_final_3/wyhash_final_3_checksum_config.cpp \ 9 | wyhash_final_4/wyhash_final_4_checksum_config.cpp \ 10 | komihash_4_3/komihash_4_3_checksum_config.cpp \ 11 | komihash_4_7/komihash_4_7_checksum_config.cpp \ 12 | komihash_5_0/komihash_5_0_checksum_config.cpp \ 13 | komihash_5_10/komihash_5_10_checksum_config.cpp \ 14 | komihash_5_27/komihash_5_27_checksum_config.cpp \ 15 | murmur3_32/murmur3_32_checksum_config.cpp \ 16 | murmur3_128/murmur3_128_checksum_config.cpp \ 17 | murmur3_128/smhasher/src/MurmurHash3.cpp \ 18 | xxh3/xxh3_checksum_config.cpp \ 19 | xxh3_128/xxh3_128_checksum_config.cpp \ 20 | xxh3/xxHash/xxhash.c \ 21 | farmna.a \ 22 | farmuo.a \ 23 | -O2 -lssl -lcrypto -o calculate_checksums -------------------------------------------------------------------------------- /reference-implementations/farmhash_na/farmhash_na_checksum_config.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include "farmhash_na_checksum_config.hpp" 17 | #include 18 | #define NAMESPACE_FOR_HASH_FUNCTIONS farmhashna 19 | #include "farmhash/src/farmhash.h" 20 | 21 | void FarmHashNaChecksumConfig::calculateHash(const uint8_t *seedBytes, 22 | uint8_t *hashBytes, const uint8_t *dataBytes, uint64_t size) const { 23 | 24 | uint64_t seed; 25 | uint64_t seed0; 26 | uint64_t seed1; 27 | memcpy(&seed, seedBytes, 8); 28 | memcpy(&seed0, seedBytes + 8, 8); 29 | memcpy(&seed1, seedBytes + 16, 8); 30 | 31 | uint64_t hash0 = farmhashna::Hash64((char*) (&dataBytes[0]), size); 32 | uint64_t hash1 = farmhashna::Hash64WithSeed((char*) (&dataBytes[0]), size, 33 | seed); 34 | uint64_t hash2 = farmhashna::Hash64WithSeeds((char*) (&dataBytes[0]), size, 35 | seed0, seed1); 36 | 37 | memcpy(hashBytes, &hash0, 8); 38 | memcpy(hashBytes + 8, &hash1, 8); 39 | memcpy(hashBytes + 16, &hash2, 8); 40 | } 41 | -------------------------------------------------------------------------------- /reference-implementations/farmhash_na/farmhash_na_checksum_config.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef FARMHASH_NA_CHECKSUM_CONFIG_HPP 17 | #define FARMHASH_NA_CHECKSUM_CONFIG_HPP 18 | 19 | #include 20 | #include 21 | 22 | class FarmHashNaChecksumConfig { 23 | 24 | public: 25 | 26 | uint64_t getSeedSize() const { 27 | return 24; 28 | } 29 | 30 | uint64_t getHashSize() const { 31 | return 24; 32 | } 33 | 34 | std::string getName() const { 35 | return "FarmHash NA"; 36 | } 37 | 38 | void calculateHash(const uint8_t *seedBytes, uint8_t *hashBytes, 39 | const uint8_t *dataBytes, uint64_t size) const; 40 | 41 | }; 42 | 43 | #endif // FARMHASH_NA_CHECKSUM_CONFIG_HPP 44 | -------------------------------------------------------------------------------- /reference-implementations/farmhash_uo/farmhash_uo_checksum_config.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include "farmhash_uo_checksum_config.hpp" 17 | #include 18 | #define NAMESPACE_FOR_HASH_FUNCTIONS farmhashuo 19 | #include "farmhash/src/farmhash.h" 20 | 21 | void FarmHashUoChecksumConfig::calculateHash(const uint8_t *seedBytes, 22 | uint8_t *hashBytes, const uint8_t *dataBytes, uint64_t size) const { 23 | 24 | uint64_t seed; 25 | uint64_t seed0; 26 | uint64_t seed1; 27 | memcpy(&seed, seedBytes, 8); 28 | memcpy(&seed0, seedBytes + 8, 8); 29 | memcpy(&seed1, seedBytes + 16, 8); 30 | 31 | uint64_t hash0 = farmhashuo::Hash64((char*) (&dataBytes[0]), size); 32 | uint64_t hash1 = farmhashuo::Hash64WithSeed((char*) (&dataBytes[0]), size, 33 | seed); 34 | uint64_t hash2 = farmhashuo::Hash64WithSeeds((char*) (&dataBytes[0]), size, 35 | seed0, seed1); 36 | 37 | memcpy(hashBytes, &hash0, 8); 38 | memcpy(hashBytes + 8, &hash1, 8); 39 | memcpy(hashBytes + 16, &hash2, 8); 40 | } 41 | -------------------------------------------------------------------------------- /reference-implementations/farmhash_uo/farmhash_uo_checksum_config.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef FARMHASH_UO_CHECKSUM_CONFIG_HPP 17 | #define FARMHASH_UO_CHECKSUM_CONFIG_HPP 18 | 19 | #include 20 | #include 21 | 22 | class FarmHashUoChecksumConfig { 23 | 24 | public: 25 | 26 | uint64_t getSeedSize() const { 27 | return 24; 28 | } 29 | 30 | uint64_t getHashSize() const { 31 | return 24; 32 | } 33 | 34 | std::string getName() const { 35 | return "FarmHash UO"; 36 | } 37 | 38 | void calculateHash(const uint8_t *seedBytes, uint8_t *hashBytes, 39 | const uint8_t *dataBytes, uint64_t size) const; 40 | 41 | }; 42 | 43 | #endif // FARMHASH_UO_CHECKSUM_CONFIG_HPP 44 | -------------------------------------------------------------------------------- /reference-implementations/imohash_1_0_2/go.mod: -------------------------------------------------------------------------------- 1 | module test 2 | 3 | go 1.18 4 | 5 | require ( 6 | github.com/kalafut/imohash v1.0.2 // indirect 7 | github.com/twmb/murmur3 v1.1.5 // indirect 8 | ) 9 | -------------------------------------------------------------------------------- /reference-implementations/imohash_1_0_2/go.sum: -------------------------------------------------------------------------------- 1 | github.com/kalafut/imohash v1.0.2 h1:j/cUPa15YvXv7abJlM+kdJIycbBMpmO7WqhPl4YB76I= 2 | github.com/kalafut/imohash v1.0.2/go.mod h1:PjHBF0vpo1q7zMqiTn0qwSTQU2wDn5QIe8S8sFQuZS8= 3 | github.com/twmb/murmur3 v1.1.5 h1:i9OLS9fkuLzBXjt6dptlAEyk58fJsSTXbRg3SgVyqgk= 4 | github.com/twmb/murmur3 v1.1.5/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ= 5 | gopkg.in/tylerb/is.v1 v1.1.2/go.mod h1:9yQB2tyIhZ5oph6Kk5Sq7cJMd9c5Jpa1p3hr9kxzPqo= 6 | -------------------------------------------------------------------------------- /reference-implementations/imohash_1_0_2/test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/sha256" 5 | "fmt" 6 | 7 | "github.com/kalafut/imohash" 8 | ) 9 | 10 | func main() { 11 | maxLength := 200000 12 | b := make([]byte, maxLength) 13 | checksumCalculator := sha256.New() 14 | for i := 0; i < maxLength; i++ { 15 | b[i] = byte(i*i + 31) 16 | } 17 | for l := 0; l < maxLength; l++ { 18 | hash := imohash.Sum(b[0:l]) 19 | checksumCalculator.Write(hash[:]) 20 | } 21 | 22 | checkSum := checksumCalculator.Sum(nil) 23 | fmt.Printf("%032x\n", checkSum) 24 | } 25 | -------------------------------------------------------------------------------- /reference-implementations/komihash_4_3/komihash_4_3_checksum_config.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include "komihash_4_3_checksum_config.hpp" 17 | #include "komihash/komihash.h" 18 | #include 19 | 20 | void Komihash4_3ChecksumConfig::calculateHash(const uint8_t *seedBytes, 21 | uint8_t *hashBytes, const uint8_t *dataBytes, uint64_t size) const { 22 | 23 | uint64_t seed; 24 | memcpy(&seed, seedBytes, 8); 25 | 26 | uint64_t hash0 = komihash((char*) (&dataBytes[0]), size, 0); 27 | uint64_t hash1 = komihash((char*) (&dataBytes[0]), size, seed); 28 | 29 | memcpy(hashBytes, &hash0, 8); 30 | memcpy(hashBytes + 8, &hash1, 8); 31 | } 32 | -------------------------------------------------------------------------------- /reference-implementations/komihash_4_3/komihash_4_3_checksum_config.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef KOMIHASH_4_3_CHECKSUM_CONFIG_HPP 17 | #define KOMIHASH_4_3_CHECKSUM_CONFIG_HPP 18 | 19 | #include 20 | #include 21 | 22 | class Komihash4_3ChecksumConfig { 23 | 24 | public: 25 | 26 | uint64_t getSeedSize() const { 27 | return 8; 28 | } 29 | 30 | uint64_t getHashSize() const { 31 | return 16; 32 | } 33 | 34 | std::string getName() const { 35 | return "Komihash 4.3"; 36 | } 37 | 38 | void calculateHash(const uint8_t *seedBytes, uint8_t *hashBytes, 39 | const uint8_t *dataBytes, uint64_t size) const; 40 | }; 41 | 42 | #endif // KOMIHASH_4_3_CHECKSUM_CONFIG_HPP 43 | -------------------------------------------------------------------------------- /reference-implementations/komihash_4_7/komihash_4_7_checksum_config.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include "komihash_4_7_checksum_config.hpp" 17 | #include "komihash/komihash.h" 18 | #include 19 | 20 | void Komihash4_7ChecksumConfig::calculateHash(const uint8_t *seedBytes, 21 | uint8_t *hashBytes, const uint8_t *dataBytes, uint64_t size) const { 22 | 23 | uint64_t seed; 24 | memcpy(&seed, seedBytes, 8); 25 | 26 | uint64_t hash0 = komihash((char*) (&dataBytes[0]), size, 0); 27 | uint64_t hash1 = komihash((char*) (&dataBytes[0]), size, seed); 28 | 29 | memcpy(hashBytes, &hash0, 8); 30 | memcpy(hashBytes + 8, &hash1, 8); 31 | } 32 | -------------------------------------------------------------------------------- /reference-implementations/komihash_4_7/komihash_4_7_checksum_config.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef KOMIHASH_4_7_CHECKSUM_CONFIG_HPP 17 | #define KOMIHASH_4_7_CHECKSUM_CONFIG_HPP 18 | 19 | #include 20 | #include 21 | 22 | class Komihash4_7ChecksumConfig { 23 | 24 | public: 25 | 26 | uint64_t getSeedSize() const { 27 | return 8; 28 | } 29 | 30 | uint64_t getHashSize() const { 31 | return 16; 32 | } 33 | 34 | std::string getName() const { 35 | return "Komihash 4.7"; 36 | } 37 | 38 | void calculateHash(const uint8_t *seedBytes, uint8_t *hashBytes, 39 | const uint8_t *dataBytes, uint64_t size) const; 40 | 41 | }; 42 | 43 | #endif // KOMIHASH_4_7_CHECKSUM_CONFIG_HPP 44 | -------------------------------------------------------------------------------- /reference-implementations/komihash_5_0/komihash_5_0_checksum_config.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include "komihash_5_0_checksum_config.hpp" 17 | #include "komihash/komihash.h" 18 | #include 19 | 20 | void Komihash5_0ChecksumConfig::calculateHash(const uint8_t *seedBytes, 21 | uint8_t *hashBytes, const uint8_t *dataBytes, uint64_t size) const { 22 | 23 | uint64_t seed; 24 | memcpy(&seed, seedBytes, 8); 25 | 26 | uint64_t hash0 = komihash((char*) (&dataBytes[0]), size, 0); 27 | uint64_t hash1 = komihash((char*) (&dataBytes[0]), size, seed); 28 | 29 | memcpy(hashBytes, &hash0, 8); 30 | memcpy(hashBytes + 8, &hash1, 8); 31 | } 32 | -------------------------------------------------------------------------------- /reference-implementations/komihash_5_0/komihash_5_0_checksum_config.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef KOMIHASH_5_0_CHECKSUM_CONFIG_HPP 17 | #define KOMIHASH_5_0_CHECKSUM_CONFIG_HPP 18 | 19 | #include 20 | #include 21 | 22 | class Komihash5_0ChecksumConfig { 23 | 24 | public: 25 | 26 | uint64_t getSeedSize() const { 27 | return 8; 28 | } 29 | 30 | uint64_t getHashSize() const { 31 | return 16; 32 | } 33 | 34 | std::string getName() const { 35 | return "Komihash 5.0"; 36 | } 37 | 38 | void calculateHash(const uint8_t *seedBytes, uint8_t *hashBytes, 39 | const uint8_t *dataBytes, uint64_t size) const; 40 | 41 | }; 42 | 43 | #endif // KOMIHASH_5_0_CHECKSUM_CONFIG_HPP 44 | -------------------------------------------------------------------------------- /reference-implementations/komihash_5_10/komihash_5_10_checksum_config.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2024 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include "komihash_5_10_checksum_config.hpp" 17 | #include "komihash/komihash.h" 18 | #include 19 | 20 | void Komihash5_10ChecksumConfig::calculateHash(const uint8_t *seedBytes, 21 | uint8_t *hashBytes, const uint8_t *dataBytes, uint64_t size) const { 22 | 23 | uint64_t seed; 24 | memcpy(&seed, seedBytes, 8); 25 | 26 | uint64_t hash0 = komihash((char*) (&dataBytes[0]), size, 0); 27 | uint64_t hash1 = komihash((char*) (&dataBytes[0]), size, seed); 28 | 29 | memcpy(hashBytes, &hash0, 8); 30 | memcpy(hashBytes + 8, &hash1, 8); 31 | } 32 | -------------------------------------------------------------------------------- /reference-implementations/komihash_5_10/komihash_5_10_checksum_config.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef KOMIHASH_5_10_CHECKSUM_CONFIG_HPP 17 | #define KOMIHASH_5_10_CHECKSUM_CONFIG_HPP 18 | 19 | #include 20 | #include 21 | 22 | class Komihash5_10ChecksumConfig { 23 | 24 | public: 25 | 26 | uint64_t getSeedSize() const { 27 | return 8; 28 | } 29 | 30 | uint64_t getHashSize() const { 31 | return 16; 32 | } 33 | 34 | std::string getName() const { 35 | return "Komihash 5.10"; 36 | } 37 | 38 | void calculateHash(const uint8_t *seedBytes, uint8_t *hashBytes, 39 | const uint8_t *dataBytes, uint64_t size) const; 40 | 41 | }; 42 | 43 | #endif // KOMIHASH_5_10_CHECKSUM_CONFIG_HPP 44 | -------------------------------------------------------------------------------- /reference-implementations/komihash_5_27/komihash_5_27_checksum_config.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include "komihash_5_27_checksum_config.hpp" 17 | #include "komihash/komihash.h" 18 | #include 19 | 20 | void Komihash5_27ChecksumConfig::calculateHash(const uint8_t *seedBytes, 21 | uint8_t *hashBytes, const uint8_t *dataBytes, uint64_t size) const { 22 | 23 | uint64_t seed; 24 | memcpy(&seed, seedBytes, 8); 25 | 26 | uint64_t hash0 = komihash((char*) (&dataBytes[0]), size, 0); 27 | uint64_t hash1 = komihash((char*) (&dataBytes[0]), size, seed); 28 | 29 | memcpy(hashBytes, &hash0, 8); 30 | memcpy(hashBytes + 8, &hash1, 8); 31 | } 32 | -------------------------------------------------------------------------------- /reference-implementations/komihash_5_27/komihash_5_27_checksum_config.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef KOMIHASH_5_27_CHECKSUM_CONFIG_HPP 17 | #define KOMIHASH_5_27_CHECKSUM_CONFIG_HPP 18 | 19 | #include 20 | #include 21 | 22 | class Komihash5_27ChecksumConfig { 23 | 24 | public: 25 | 26 | uint64_t getSeedSize() const { 27 | return 8; 28 | } 29 | 30 | uint64_t getHashSize() const { 31 | return 16; 32 | } 33 | 34 | std::string getName() const { 35 | return "Komihash 5.27"; 36 | } 37 | 38 | void calculateHash(const uint8_t *seedBytes, uint8_t *hashBytes, 39 | const uint8_t *dataBytes, uint64_t size) const; 40 | 41 | }; 42 | 43 | #endif // KOMIHASH_5_27_CHECKSUM_CONFIG_HPP 44 | -------------------------------------------------------------------------------- /reference-implementations/murmur3_128/murmur3_128_checksum_config.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include "murmur3_128_checksum_config.hpp" 17 | #include "smhasher/src/MurmurHash3.h" 18 | #include 19 | 20 | void Murmur3_128_ChecksumConfig::calculateHash(const uint8_t *seedBytes, 21 | uint8_t *hashBytes, const uint8_t *dataBytes, uint64_t size) const { 22 | 23 | uint32_t seed; 24 | memcpy(&seed, seedBytes, 4); 25 | MurmurHash3_x64_128(dataBytes, size, 0, hashBytes); 26 | MurmurHash3_x64_128(dataBytes, size, seed, hashBytes + 16); 27 | } 28 | -------------------------------------------------------------------------------- /reference-implementations/murmur3_128/murmur3_128_checksum_config.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef MURMUR3_128_CHECKSUM_CONFIG_HPP 17 | #define MURMUR3_128_CHECKSUM_CONFIG_HPP 18 | 19 | #include 20 | #include 21 | 22 | class Murmur3_128_ChecksumConfig { 23 | 24 | public: 25 | 26 | uint64_t getSeedSize() const { 27 | return 4; 28 | } 29 | 30 | uint64_t getHashSize() const { 31 | return 32; 32 | } 33 | 34 | std::string getName() const { 35 | return "Murmur3 128"; 36 | } 37 | 38 | void calculateHash(const uint8_t *seedBytes, uint8_t *hashBytes, 39 | const uint8_t *dataBytes, uint64_t size) const; 40 | }; 41 | 42 | #endif // MURMUR3_128_CHECKSUM_CONFIG_HPP 43 | -------------------------------------------------------------------------------- /reference-implementations/murmur3_32/murmur3_32_checksum_config.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include "murmur3_32_checksum_config.hpp" 17 | #include "smhasher/src/MurmurHash3.h" 18 | #include 19 | 20 | void Murmur3_32_ChecksumConfig::calculateHash(const uint8_t *seedBytes, 21 | uint8_t *hashBytes, const uint8_t *dataBytes, uint64_t size) const { 22 | 23 | uint32_t seed; 24 | memcpy(&seed, seedBytes, 4); 25 | MurmurHash3_x86_32(dataBytes, size, 0, hashBytes); 26 | MurmurHash3_x86_32(dataBytes, size, seed, hashBytes + 4); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /reference-implementations/murmur3_32/murmur3_32_checksum_config.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef MURMUR3_32_CHECKSUM_CONFIG_HPP 17 | #define MURMUR3_32_CHECKSUM_CONFIG_HPP 18 | 19 | #include 20 | #include 21 | 22 | class Murmur3_32_ChecksumConfig { 23 | 24 | public: 25 | 26 | uint64_t getSeedSize() const { 27 | return 4; 28 | } 29 | 30 | uint64_t getHashSize() const { 31 | return 8; 32 | } 33 | 34 | std::string getName() const { 35 | return "Murmur3 32"; 36 | } 37 | 38 | void calculateHash(const uint8_t *seedBytes, uint8_t *hashBytes, 39 | const uint8_t *dataBytes, uint64_t size) const; 40 | 41 | }; 42 | 43 | #endif // MURMUR3_32_CHECKSUM_CONFIG_HPP 44 | -------------------------------------------------------------------------------- /reference-implementations/polymur-hash_2_0/polymur-hash_2_0_checksum_config.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2024 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include "polymur-hash_2_0_checksum_config.hpp" 17 | #include "polymur-hash/polymur-hash.h" 18 | #include 19 | 20 | void PolymurHash_2_0_ChecksumConfig::calculateHash(const uint8_t *seedBytes, 21 | uint8_t *hashBytes, const uint8_t *dataBytes, uint64_t size) const { 22 | 23 | uint64_t seed0; 24 | uint64_t seed1; 25 | uint64_t tweak; 26 | memcpy(&tweak, seedBytes, 8); 27 | memcpy(&seed0, seedBytes + 8, 8); 28 | memcpy(&seed1, seedBytes + 16, 8); 29 | PolymurHashParams params0; 30 | PolymurHashParams params1; 31 | 32 | polymur_init_params_from_seed(¶ms0, seed0); 33 | polymur_init_params(¶ms1, seed0, seed1); 34 | 35 | uint64_t hash0 = polymur_hash(dataBytes, size, ¶ms0, tweak); 36 | uint64_t hash1 = polymur_hash(dataBytes, size, ¶ms1, tweak); 37 | 38 | memcpy(hashBytes, &hash0, 8); 39 | memcpy(hashBytes + 8, &hash1, 8); 40 | } 41 | -------------------------------------------------------------------------------- /reference-implementations/polymur-hash_2_0/polymur-hash_2_0_checksum_config.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef POLYMURHASH_2_0_CHECKSUM_CONFIG_HPP 17 | #define POLYMURHASH_2_0_CHECKSUM_CONFIG_HPP 18 | 19 | #include 20 | #include 21 | 22 | class PolymurHash_2_0_ChecksumConfig { 23 | 24 | public: 25 | 26 | uint64_t getSeedSize() const { 27 | return 24; 28 | } 29 | 30 | uint64_t getHashSize() const { 31 | return 16; 32 | } 33 | 34 | std::string getName() const { 35 | return "PolymurHash 2.0"; 36 | } 37 | 38 | void calculateHash(const uint8_t *seedBytes, uint8_t *hashBytes, 39 | const uint8_t *dataBytes, uint64_t size) const; 40 | 41 | }; 42 | 43 | #endif // POLYMURHASH_2_0_CHECKSUM_CONFIG_HPP 44 | -------------------------------------------------------------------------------- /reference-implementations/wyhash_final_3/wyhash_final_3_checksum_config.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include "wyhash_final_3_checksum_config.hpp" 17 | #include "wyhash/wyhash.h" 18 | #include 19 | 20 | void WyhashFinal3ChecksumConfig::calculateHash(const uint8_t *seedBytes, 21 | uint8_t *hashBytes, const uint8_t *dataBytes, uint64_t size) const { 22 | 23 | uint64_t seed1, seed2; 24 | memcpy(&seed1, seedBytes, 8); 25 | memcpy(&seed2, seedBytes + 8, 8); 26 | 27 | uint64_t rand; 28 | memcpy(&rand, seedBytes + 16, 8); 29 | 30 | uint64_t hash0 = wyhash(dataBytes, size, 0, _wyp); 31 | uint64_t hash1 = wyhash(dataBytes, size, seed1, _wyp); 32 | uint64_t hash2 = 0; 33 | uint64_t hash3 = 0; 34 | 35 | if ((rand & UINT64_C(0x3F)) == 0) { 36 | // secret computation is relatively slow, therefore do it 37 | // just in 1 out of 64 cases 38 | uint64_t _wyp2[4]; 39 | make_secret(seed2, _wyp2); 40 | hash2 = wyhash(dataBytes, size, 0, _wyp2); 41 | hash3 = wyhash(dataBytes, size, seed1, _wyp2); 42 | } 43 | 44 | memcpy(hashBytes, &hash0, 8); 45 | memcpy(hashBytes + 8, &hash1, 8); 46 | memcpy(hashBytes + 16, &hash2, 8); 47 | memcpy(hashBytes + 24, &hash3, 8); 48 | } 49 | -------------------------------------------------------------------------------- /reference-implementations/wyhash_final_3/wyhash_final_3_checksum_config.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef WYHASH_FINAL_3_CHECKSUM_CONFIG_HPP 17 | #define WYHASH_FINAL_3_CHECKSUM_CONFIG_HPP 18 | 19 | #include 20 | #include 21 | 22 | class WyhashFinal3ChecksumConfig { 23 | 24 | public: 25 | 26 | uint64_t getSeedSize() const { 27 | return 24; 28 | } 29 | 30 | uint64_t getHashSize() const { 31 | return 32; 32 | } 33 | 34 | std::string getName() const { 35 | return "Wyhash final 3"; 36 | } 37 | 38 | void calculateHash(const uint8_t *seedBytes, uint8_t *hashBytes, 39 | const uint8_t *dataBytes, uint64_t size) const; 40 | 41 | }; 42 | 43 | #endif // WYHASH_FINAL_3_CHECKSUM_CONFIG_HPP 44 | -------------------------------------------------------------------------------- /reference-implementations/wyhash_final_4/wyhash_final_4_checksum_config.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include "wyhash_final_4_checksum_config.hpp" 17 | #include "wyhash/wyhash.h" 18 | #include 19 | 20 | void WyhashFinal4ChecksumConfig::calculateHash(const uint8_t *seedBytes, 21 | uint8_t *hashBytes, const uint8_t *dataBytes, uint64_t size) const { 22 | 23 | uint64_t seed1, seed2; 24 | memcpy(&seed1, seedBytes, 8); 25 | memcpy(&seed2, seedBytes + 8, 8); 26 | 27 | uint64_t rand; 28 | memcpy(&rand, seedBytes + 16, 8); 29 | 30 | uint64_t hash0 = wyhash(dataBytes, size, 0, _wyp); 31 | uint64_t hash1 = wyhash(dataBytes, size, seed1, _wyp); 32 | uint64_t hash2 = 0; 33 | uint64_t hash3 = 0; 34 | 35 | if ((rand & UINT64_C(0x3F)) == 0) { 36 | // secret computation is relatively slow, therefore do it 37 | // just in 1 out of 64 cases 38 | uint64_t _wyp2[4]; 39 | make_secret(seed2, _wyp2); 40 | hash2 = wyhash(dataBytes, size, 0, _wyp2); 41 | hash3 = wyhash(dataBytes, size, seed1, _wyp2); 42 | } 43 | 44 | memcpy(hashBytes, &hash0, 8); 45 | memcpy(hashBytes + 8, &hash1, 8); 46 | memcpy(hashBytes + 16, &hash2, 8); 47 | memcpy(hashBytes + 24, &hash3, 8); 48 | } 49 | -------------------------------------------------------------------------------- /reference-implementations/wyhash_final_4/wyhash_final_4_checksum_config.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef WYHASH_FINAL_4_CHECKSUM_CONFIG_HPP 17 | #define WYHASH_FINAL_4_CHECKSUM_CONFIG_HPP 18 | 19 | #include 20 | #include 21 | 22 | class WyhashFinal4ChecksumConfig { 23 | 24 | public: 25 | 26 | uint64_t getSeedSize() const { 27 | return 24; 28 | } 29 | 30 | uint64_t getHashSize() const { 31 | return 32; 32 | } 33 | 34 | std::string getName() const { 35 | return "Wyhash final 4"; 36 | } 37 | 38 | void calculateHash(const uint8_t *seedBytes, uint8_t *hashBytes, 39 | const uint8_t *dataBytes, uint64_t size) const; 40 | 41 | }; 42 | 43 | #endif // WYHASH_FINAL_4_CHECKSUM_CONFIG_HPP 44 | -------------------------------------------------------------------------------- /reference-implementations/xxh3/xxh3_checksum_config.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include "xxh3_checksum_config.hpp" 17 | #include "xxhash/xxhash.h" 18 | #include 19 | 20 | void XXH3ChecksumConfig::calculateHash(const uint8_t *seedBytes, 21 | uint8_t *hashBytes, const uint8_t *dataBytes, uint64_t size) const { 22 | 23 | uint64_t seed; 24 | memcpy(&seed, seedBytes, 8); 25 | 26 | uint64_t hash0 = XXH3_64bits((char*) (&dataBytes[0]), size); 27 | uint64_t hash1 = XXH3_64bits_withSeed((char*) (&dataBytes[0]), size, seed); 28 | 29 | memcpy(hashBytes, &hash0, 8); 30 | memcpy(hashBytes + 8, &hash1, 8); 31 | } 32 | -------------------------------------------------------------------------------- /reference-implementations/xxh3/xxh3_checksum_config.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef XXH3_CHECKSUM_CONFIG_HPP 17 | #define XXH3_CHECKSUM_CONFIG_HPP 18 | 19 | #include 20 | #include 21 | 22 | class XXH3ChecksumConfig { 23 | 24 | public: 25 | 26 | uint64_t getSeedSize() const { 27 | return 8; 28 | } 29 | 30 | uint64_t getHashSize() const { 31 | return 16; 32 | } 33 | 34 | std::string getName() const { 35 | return "XXH3"; 36 | } 37 | 38 | void calculateHash(const uint8_t *seedBytes, uint8_t *hashBytes, 39 | const uint8_t *dataBytes, uint64_t size) const; 40 | 41 | }; 42 | 43 | #endif // XXH3_CHECKSUM_CONFIG_HPP 44 | -------------------------------------------------------------------------------- /reference-implementations/xxh3_128/xxh3_128_checksum_config.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #include "xxh3_128_checksum_config.hpp" 17 | #include "xxhash/xxhash.h" 18 | #include 19 | 20 | void XXH3_128_ChecksumConfig::calculateHash(const uint8_t *seedBytes, 21 | uint8_t *hashBytes, const uint8_t *dataBytes, uint64_t size) const { 22 | 23 | uint64_t seed; 24 | memcpy(&seed, seedBytes, 8); 25 | 26 | XXH128_hash_t hash0 = XXH3_128bits((char*) (&dataBytes[0]), size); 27 | XXH128_hash_t hash1 = XXH3_128bits_withSeed((char*) (&dataBytes[0]), size, 28 | seed); 29 | 30 | memcpy(hashBytes, &hash0, 16); 31 | memcpy(hashBytes + 16, &hash1, 16); 32 | } 33 | -------------------------------------------------------------------------------- /reference-implementations/xxh3_128/xxh3_128_checksum_config.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | #ifndef XXH3_128_CHECKSUM_CONFIG_HPP 17 | #define XXH3_128_CHECKSUM_CONFIG_HPP 18 | 19 | #include 20 | #include 21 | 22 | class XXH3_128_ChecksumConfig { 23 | 24 | public: 25 | 26 | uint64_t getSeedSize() const { 27 | return 8; 28 | } 29 | 30 | uint64_t getHashSize() const { 31 | return 32; 32 | } 33 | 34 | std::string getName() const { 35 | return "XXH3_128"; 36 | } 37 | 38 | void calculateHash(const uint8_t *seedBytes, uint8_t *hashBytes, 39 | const uint8_t *dataBytes, uint64_t size) const; 40 | 41 | }; 42 | 43 | #endif // XXH3_128_CHECKSUM_CONFIG_HPP 44 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | black==25.1.0 2 | click==8.1.7 3 | GitPython==3.1.41 4 | matplotlib==3.8.2 5 | pandas==2.1.4 6 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = "hash4j" 2 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/consistent/ConsistentJumpBackBucketHasherPerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023-2024 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.consistent; 17 | 18 | import com.dynatrace.hash4j.random.PseudoRandomGeneratorProvider; 19 | import java.util.SplittableRandom; 20 | import org.openjdk.jmh.annotations.*; 21 | import org.openjdk.jmh.infra.Blackhole; 22 | 23 | public class ConsistentJumpBackBucketHasherPerformanceTest { 24 | 25 | private static final ConsistentBucketHasher CONSISTENT_BUCKET_HASHER = 26 | ConsistentHashing.jumpBackHash(PseudoRandomGeneratorProvider.splitMix64_V1()); 27 | 28 | @State(Scope.Thread) 29 | public static class TestState { 30 | 31 | @Param({"1", "10", "100", "1000", "10000", "100000", "1000000"}) 32 | int numBuckets; 33 | 34 | SplittableRandom random; 35 | 36 | @Setup 37 | public void init() { 38 | random = new SplittableRandom(0x87c5950e6677341eL); 39 | } 40 | } 41 | 42 | @Benchmark 43 | @BenchmarkMode(Mode.AverageTime) 44 | public void getBucket(TestState testState, Blackhole blackhole) { 45 | int bucket = 46 | CONSISTENT_BUCKET_HASHER.getBucket(testState.random.nextLong(), testState.numBuckets); 47 | blackhole.consume(bucket); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/consistent/ConsistentJumpBucketHasherPerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.consistent; 17 | 18 | import com.dynatrace.hash4j.random.PseudoRandomGeneratorProvider; 19 | import java.util.SplittableRandom; 20 | import org.openjdk.jmh.annotations.*; 21 | import org.openjdk.jmh.infra.Blackhole; 22 | 23 | public class ConsistentJumpBucketHasherPerformanceTest { 24 | 25 | private static final ConsistentBucketHasher CONSISTENT_BUCKET_HASHER = 26 | ConsistentHashing.jumpHash(PseudoRandomGeneratorProvider.splitMix64_V1()); 27 | 28 | @State(Scope.Thread) 29 | public static class TestState { 30 | 31 | @Param({"1", "10", "100", "1000", "10000", "100000", "1000000"}) 32 | int numBuckets; 33 | 34 | SplittableRandom random; 35 | 36 | @Setup 37 | public void init() { 38 | random = new SplittableRandom(0x87c5950e6677341eL); 39 | } 40 | } 41 | 42 | @Benchmark 43 | @BenchmarkMode(Mode.AverageTime) 44 | public void getBucket(TestState testState, Blackhole blackhole) { 45 | int bucket = 46 | CONSISTENT_BUCKET_HASHER.getBucket(testState.random.nextLong(), testState.numBuckets); 47 | blackhole.consume(bucket); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/consistent/ImprovedConsistentWeightedSamplingPerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.consistent; 17 | 18 | import com.dynatrace.hash4j.random.PseudoRandomGeneratorProvider; 19 | import java.util.SplittableRandom; 20 | import org.openjdk.jmh.annotations.*; 21 | import org.openjdk.jmh.infra.Blackhole; 22 | 23 | public class ImprovedConsistentWeightedSamplingPerformanceTest { 24 | 25 | private static final ConsistentBucketHasher CONSISTENT_BUCKET_HASHER = 26 | ConsistentHashing.improvedConsistentWeightedSampling( 27 | PseudoRandomGeneratorProvider.splitMix64_V1()); 28 | 29 | @State(Scope.Thread) 30 | public static class TestState { 31 | 32 | @Param({"1", "10", "100", "1000", "10000", "100000", "1000000"}) 33 | int numBuckets; 34 | 35 | SplittableRandom random; 36 | 37 | @Setup 38 | public void init() { 39 | random = new SplittableRandom(0x87c5950e6677341eL); 40 | } 41 | } 42 | 43 | @Benchmark 44 | @BenchmarkMode(Mode.AverageTime) 45 | public void getBucket(TestState testState, Blackhole blackhole) { 46 | int bucket = 47 | CONSISTENT_BUCKET_HASHER.getBucket(testState.random.nextLong(), testState.numBuckets); 48 | blackhole.consume(bucket); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/consistent/ModuloAssignmentPerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023-2024 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.consistent; 17 | 18 | import java.util.SplittableRandom; 19 | import org.openjdk.jmh.annotations.*; 20 | import org.openjdk.jmh.infra.Blackhole; 21 | 22 | public class ModuloAssignmentPerformanceTest { 23 | 24 | @State(Scope.Thread) 25 | public static class TestState { 26 | 27 | @Param({"1", "10", "100", "1000", "10000", "100000", "1000000"}) 28 | int numBuckets; 29 | 30 | SplittableRandom random; 31 | 32 | @Setup 33 | public void init() { 34 | random = new SplittableRandom(0x87c5950e6677341eL); 35 | } 36 | } 37 | 38 | @Benchmark 39 | @BenchmarkMode(Mode.AverageTime) 40 | public void getBucket(TestState testState, Blackhole blackhole) { 41 | int bucket = (int) ((testState.random.nextLong() & 0x7FFFFFFFFFFFFFFFL) % testState.numBuckets); 42 | blackhole.consume(bucket); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/consistent/RandomAssignmentPerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023-2024 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.consistent; 17 | 18 | import com.dynatrace.hash4j.random.PseudoRandomGenerator; 19 | import com.dynatrace.hash4j.random.PseudoRandomGeneratorProvider; 20 | import java.util.SplittableRandom; 21 | import org.openjdk.jmh.annotations.*; 22 | import org.openjdk.jmh.infra.Blackhole; 23 | 24 | public class RandomAssignmentPerformanceTest { 25 | 26 | private static final PseudoRandomGenerator PSEUDO_RANDOM_GENERATOR = 27 | PseudoRandomGeneratorProvider.splitMix64_V1().create(); 28 | 29 | @State(Scope.Thread) 30 | public static class TestState { 31 | 32 | @Param({"1", "10", "100", "1000", "10000", "100000", "1000000"}) 33 | int numBuckets; 34 | 35 | SplittableRandom random; 36 | 37 | @Setup 38 | public void init() { 39 | random = new SplittableRandom(0x87c5950e6677341eL); 40 | } 41 | } 42 | 43 | @Benchmark 44 | @BenchmarkMode(Mode.AverageTime) 45 | public void getBucket(TestState testState, Blackhole blackhole) { 46 | PSEUDO_RANDOM_GENERATOR.reset(testState.random.nextLong()); 47 | int bucket = PSEUDO_RANDOM_GENERATOR.uniformInt(testState.numBuckets); 48 | blackhole.consume(bucket); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/consistent/RandomNumberPerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023-2024 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.consistent; 17 | 18 | import java.util.SplittableRandom; 19 | import org.openjdk.jmh.annotations.*; 20 | import org.openjdk.jmh.infra.Blackhole; 21 | 22 | // test to measure costs for random value generation to simulate hash values 23 | public class RandomNumberPerformanceTest { 24 | 25 | @State(Scope.Thread) 26 | public static class TestState { 27 | 28 | SplittableRandom random; 29 | 30 | @Setup 31 | public void init() { 32 | random = new SplittableRandom(0x87c5950e6677341eL); 33 | } 34 | } 35 | 36 | @Benchmark 37 | @BenchmarkMode(Mode.AverageTime) 38 | public void getBucket(TestState testState, Blackhole blackhole) { 39 | blackhole.consume(testState.random.nextLong()); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/AbstactHasher128PerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | import org.openjdk.jmh.infra.Blackhole; 19 | 20 | public abstract class AbstactHasher128PerformanceTest extends AbstractPerformanceTest { 21 | 22 | protected static final HashFunnel CHARS_FUNNEL = (s, sink) -> sink.putChars(s); 23 | protected static final HashFunnel BYTES_FUNNEL = (s, sink) -> sink.putBytes(s); 24 | 25 | @Override 26 | protected void hashObject(TestObject testObject, Blackhole blackhole) { 27 | blackhole.consume(getHasherInstance().hashTo128Bits(testObject, TestObject::contributeToHash)); 28 | } 29 | 30 | @Override 31 | protected void hashBytesDirect(byte[] b, Blackhole blackhole) { 32 | blackhole.consume(getHasherInstance().hashBytesTo128Bits(b)); 33 | } 34 | 35 | @Override 36 | protected void hashBytesIndirect(byte[] b, Blackhole blackhole) { 37 | blackhole.consume(getHasherInstance().hashTo128Bits(b, BYTES_FUNNEL)); 38 | } 39 | 40 | @Override 41 | protected void hashCharsDirect(String s, Blackhole blackhole) { 42 | blackhole.consume(getHasherInstance().hashCharsTo128Bits(s)); 43 | } 44 | 45 | @Override 46 | protected void hashCharsIndirect(String s, Blackhole blackhole) { 47 | blackhole.consume(getHasherInstance().hashTo128Bits(s, CHARS_FUNNEL)); 48 | } 49 | 50 | protected abstract Hasher128 getHasherInstance(); 51 | } 52 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/AbstactHasher32PerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | import org.openjdk.jmh.infra.Blackhole; 19 | 20 | public abstract class AbstactHasher32PerformanceTest extends AbstractPerformanceTest { 21 | 22 | protected static final HashFunnel CHARS_FUNNEL = (s, sink) -> sink.putChars(s); 23 | protected static final HashFunnel BYTES_FUNNEL = (s, sink) -> sink.putBytes(s); 24 | 25 | @Override 26 | protected void hashObject(TestObject testObject, Blackhole blackhole) { 27 | blackhole.consume(getHasherInstance().hashToInt(testObject, TestObject::contributeToHash)); 28 | } 29 | 30 | @Override 31 | protected void hashBytesDirect(byte[] b, Blackhole blackhole) { 32 | blackhole.consume(getHasherInstance().hashBytesToInt(b)); 33 | } 34 | 35 | @Override 36 | protected void hashCharsDirect(String c, Blackhole blackhole) { 37 | blackhole.consume(getHasherInstance().hashCharsToInt(c)); 38 | } 39 | 40 | @Override 41 | protected void hashCharsIndirect(String s, Blackhole blackhole) { 42 | blackhole.consume(getHasherInstance().hashToInt(s, CHARS_FUNNEL)); 43 | } 44 | 45 | @Override 46 | protected void hashBytesIndirect(byte[] b, Blackhole blackhole) { 47 | blackhole.consume(getHasherInstance().hashToInt(b, BYTES_FUNNEL)); 48 | } 49 | 50 | protected abstract Hasher32 getHasherInstance(); 51 | } 52 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/AbstactHasher64PerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | import org.openjdk.jmh.infra.Blackhole; 19 | 20 | public abstract class AbstactHasher64PerformanceTest extends AbstractPerformanceTest { 21 | 22 | protected static final HashFunnel CHARS_FUNNEL = (s, sink) -> sink.putChars(s); 23 | protected static final HashFunnel BYTES_FUNNEL = (s, sink) -> sink.putBytes(s); 24 | 25 | @Override 26 | protected void hashObject(TestObject testObject, Blackhole blackhole) { 27 | blackhole.consume(getHasherInstance().hashToLong(testObject, TestObject::contributeToHash)); 28 | } 29 | 30 | @Override 31 | protected void hashBytesDirect(byte[] b, Blackhole blackhole) { 32 | blackhole.consume(getHasherInstance().hashBytesToLong(b)); 33 | } 34 | 35 | @Override 36 | protected void hashBytesIndirect(byte[] b, Blackhole blackhole) { 37 | blackhole.consume(getHasherInstance().hashToLong(b, BYTES_FUNNEL)); 38 | } 39 | 40 | @Override 41 | protected void hashCharsDirect(String s, Blackhole blackhole) { 42 | blackhole.consume(getHasherInstance().hashCharsToLong(s)); 43 | } 44 | 45 | @Override 46 | protected void hashCharsIndirect(String s, Blackhole blackhole) { 47 | blackhole.consume(getHasherInstance().hashToLong(s, CHARS_FUNNEL)); 48 | } 49 | 50 | protected abstract Hasher64 getHasherInstance(); 51 | } 52 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/AbstractGuava128BitPerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | import com.google.common.hash.Funnel; 19 | import com.google.common.hash.HashFunction; 20 | import org.openjdk.jmh.infra.Blackhole; 21 | 22 | public abstract class AbstractGuava128BitPerformanceTest extends AbstractPerformanceTest { 23 | 24 | protected static final Funnel CHARS_FUNNEL = (s, sink) -> sink.putUnencodedChars(s); 25 | protected static final Funnel BYTES_FUNNEL = (s, sink) -> sink.putBytes(s); 26 | 27 | @Override 28 | protected void hashObject(TestObject testObject, Blackhole blackhole) { 29 | blackhole.consume(createHashFunction().hashObject(testObject, TestObject::contributeToHash)); 30 | } 31 | 32 | @Override 33 | protected void hashBytesDirect(byte[] b, Blackhole blackhole) { 34 | blackhole.consume(createHashFunction().hashBytes(b)); 35 | } 36 | 37 | @Override 38 | protected void hashCharsDirect(String s, Blackhole blackhole) { 39 | blackhole.consume(createHashFunction().hashUnencodedChars(s)); 40 | } 41 | 42 | @Override 43 | protected void hashCharsIndirect(String s, Blackhole blackhole) { 44 | blackhole.consume(createHashFunction().hashObject(s, CHARS_FUNNEL)); 45 | } 46 | 47 | @Override 48 | protected void hashBytesIndirect(byte[] b, Blackhole blackhole) { 49 | blackhole.consume(createHashFunction().hashObject(b, BYTES_FUNNEL)); 50 | } 51 | 52 | protected abstract HashFunction createHashFunction(); 53 | } 54 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/AbstractGuava32BitPerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | import com.google.common.hash.Funnel; 19 | import com.google.common.hash.HashFunction; 20 | import org.openjdk.jmh.infra.Blackhole; 21 | 22 | public abstract class AbstractGuava32BitPerformanceTest extends AbstractPerformanceTest { 23 | 24 | protected static final Funnel CHARS_FUNNEL = (s, sink) -> sink.putUnencodedChars(s); 25 | protected static final Funnel BYTES_FUNNEL = (s, sink) -> sink.putBytes(s); 26 | 27 | @Override 28 | protected void hashObject(TestObject testObject, Blackhole blackhole) { 29 | blackhole.consume( 30 | createHashFunction().hashObject(testObject, TestObject::contributeToHash).asInt()); 31 | } 32 | 33 | @Override 34 | protected void hashBytesDirect(byte[] b, Blackhole blackhole) { 35 | blackhole.consume(createHashFunction().hashBytes(b).asInt()); 36 | } 37 | 38 | @Override 39 | protected void hashCharsDirect(String s, Blackhole blackhole) { 40 | blackhole.consume(createHashFunction().hashUnencodedChars(s).asInt()); 41 | } 42 | 43 | @Override 44 | protected void hashCharsIndirect(String s, Blackhole blackhole) { 45 | blackhole.consume(createHashFunction().hashObject(s, CHARS_FUNNEL).asInt()); 46 | } 47 | 48 | @Override 49 | protected void hashBytesIndirect(byte[] b, Blackhole blackhole) { 50 | blackhole.consume(createHashFunction().hashObject(b, BYTES_FUNNEL).asInt()); 51 | } 52 | 53 | protected abstract HashFunction createHashFunction(); 54 | } 55 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/AbstractGuava64BitPerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | import com.google.common.hash.Funnel; 19 | import com.google.common.hash.HashFunction; 20 | import org.openjdk.jmh.infra.Blackhole; 21 | 22 | public abstract class AbstractGuava64BitPerformanceTest extends AbstractPerformanceTest { 23 | 24 | protected static final Funnel CHARS_FUNNEL = (s, sink) -> sink.putUnencodedChars(s); 25 | protected static final Funnel BYTES_FUNNEL = (s, sink) -> sink.putBytes(s); 26 | 27 | @Override 28 | protected void hashObject(TestObject testObject, Blackhole blackhole) { 29 | blackhole.consume( 30 | createHashFunction().hashObject(testObject, TestObject::contributeToHash).asLong()); 31 | } 32 | 33 | @Override 34 | protected void hashBytesDirect(byte[] b, Blackhole blackhole) { 35 | blackhole.consume(createHashFunction().hashBytes(b).asLong()); 36 | } 37 | 38 | @Override 39 | protected void hashCharsDirect(String s, Blackhole blackhole) { 40 | blackhole.consume(createHashFunction().hashUnencodedChars(s).asLong()); 41 | } 42 | 43 | @Override 44 | protected void hashCharsIndirect(String s, Blackhole blackhole) { 45 | blackhole.consume(createHashFunction().hashObject(s, CHARS_FUNNEL).asLong()); 46 | } 47 | 48 | @Override 49 | protected void hashBytesIndirect(byte[] b, Blackhole blackhole) { 50 | blackhole.consume(createHashFunction().hashObject(b, BYTES_FUNNEL).asLong()); 51 | } 52 | 53 | protected abstract HashFunction createHashFunction(); 54 | } 55 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/AbstractZeroAllocationHashing128BitPerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | import com.google.common.io.ByteArrayDataOutput; 19 | import com.google.common.io.ByteStreams; 20 | import java.io.IOException; 21 | import net.openhft.hashing.LongTupleHashFunction; 22 | import org.openjdk.jmh.infra.Blackhole; 23 | 24 | public abstract class AbstractZeroAllocationHashing128BitPerformanceTest 25 | extends AbstractPerformanceTest { 26 | 27 | @Override 28 | protected void hashBytesDirect(byte[] b, Blackhole blackhole) { 29 | blackhole.consume(createHashFunction().hashBytes(b)); 30 | } 31 | 32 | @Override 33 | protected void hashCharsDirect(String s, Blackhole blackhole) { 34 | blackhole.consume(createHashFunction().hashChars(s)); 35 | } 36 | 37 | @Override 38 | protected void hashBytesIndirect(byte[] b, Blackhole blackhole) { 39 | throw new UnsupportedOperationException(); 40 | } 41 | 42 | @Override 43 | protected void hashCharsIndirect(String s, Blackhole blackhole) { 44 | throw new UnsupportedOperationException(); 45 | } 46 | 47 | protected abstract LongTupleHashFunction createHashFunction(); 48 | 49 | @Override 50 | protected void hashObject(TestObject testObject, Blackhole blackhole) { 51 | try { 52 | ByteArrayDataOutput dataOutput = ByteStreams.newDataOutput(); 53 | testObject.writeToDataOutput(dataOutput); 54 | hashBytesDirect(dataOutput.toByteArray(), blackhole); 55 | } catch (IOException e) { 56 | throw new RuntimeException(e); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/AbstractZeroAllocationHashing64BitPerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | import com.google.common.io.ByteArrayDataOutput; 19 | import com.google.common.io.ByteStreams; 20 | import java.io.IOException; 21 | import net.openhft.hashing.LongHashFunction; 22 | import org.openjdk.jmh.infra.Blackhole; 23 | 24 | public abstract class AbstractZeroAllocationHashing64BitPerformanceTest 25 | extends AbstractPerformanceTest { 26 | 27 | @Override 28 | protected void hashBytesDirect(byte[] b, Blackhole blackhole) { 29 | blackhole.consume(createHashFunction().hashBytes(b)); 30 | } 31 | 32 | @Override 33 | protected void hashCharsDirect(String s, Blackhole blackhole) { 34 | blackhole.consume(createHashFunction().hashChars(s)); 35 | } 36 | 37 | @Override 38 | protected void hashBytesIndirect(byte[] b, Blackhole blackhole) { 39 | throw new UnsupportedOperationException(); 40 | } 41 | 42 | @Override 43 | protected void hashCharsIndirect(String s, Blackhole blackhole) { 44 | throw new UnsupportedOperationException(); 45 | } 46 | 47 | protected abstract LongHashFunction createHashFunction(); 48 | 49 | @Override 50 | protected void hashObject(TestObject testObject, Blackhole blackhole) { 51 | try { 52 | ByteArrayDataOutput dataOutput = ByteStreams.newDataOutput(); 53 | testObject.writeToDataOutput(dataOutput); 54 | hashBytesDirect(dataOutput.toByteArray(), blackhole); 55 | } catch (IOException e) { 56 | throw new RuntimeException(e); 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/FarmHashNaGuavaPerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | import com.google.common.hash.HashFunction; 19 | import com.google.common.hash.Hashing; 20 | 21 | public class FarmHashNaGuavaPerformanceTest extends AbstractGuava64BitPerformanceTest { 22 | private static final HashFunction HASH_FUNCTION = Hashing.farmHashFingerprint64(); 23 | 24 | @Override 25 | protected HashFunction createHashFunction() { 26 | return HASH_FUNCTION; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/FarmHashNaPerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | public class FarmHashNaPerformanceTest extends AbstactHasher64PerformanceTest { 19 | private static final Hasher64 HASHER_INSTANCE = Hashing.farmHashNa(); 20 | 21 | @Override 22 | protected Hasher64 getHasherInstance() { 23 | return HASHER_INSTANCE; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/FarmHashNaZeroAllocationHashingPerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | import net.openhft.hashing.LongHashFunction; 19 | 20 | public class FarmHashNaZeroAllocationHashingPerformanceTest 21 | extends AbstractZeroAllocationHashing64BitPerformanceTest { 22 | 23 | private static final LongHashFunction HASH_FUNCTION = LongHashFunction.farmNa(); 24 | 25 | @Override 26 | protected LongHashFunction createHashFunction() { 27 | return HASH_FUNCTION; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/FarmHashUoPerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2024 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | public class FarmHashUoPerformanceTest extends AbstactHasher64PerformanceTest { 19 | private static final Hasher64 HASHER_INSTANCE = Hashing.farmHashUo(); 20 | 21 | @Override 22 | protected Hasher64 getHasherInstance() { 23 | return HASHER_INSTANCE; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/FarmHashUoZeroAllocationHashingPerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2024 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | import net.openhft.hashing.LongHashFunction; 19 | 20 | public class FarmHashUoZeroAllocationHashingPerformanceTest 21 | extends AbstractZeroAllocationHashing64BitPerformanceTest { 22 | 23 | private static final LongHashFunction HASH_FUNCTION = LongHashFunction.farmUo(); 24 | 25 | @Override 26 | protected LongHashFunction createHashFunction() { 27 | return HASH_FUNCTION; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/Komihash4_3PerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | public class Komihash4_3PerformanceTest extends AbstactHasher64PerformanceTest { 19 | 20 | private static final Hasher64 HASHER_INSTANCE = Hashing.komihash4_3(); 21 | 22 | @Override 23 | protected Hasher64 getHasherInstance() { 24 | return HASHER_INSTANCE; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/Komihash5_0PerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | public class Komihash5_0PerformanceTest extends AbstactHasher64PerformanceTest { 19 | 20 | private static final Hasher64 HASHER_INSTANCE = Hashing.komihash5_0(); 21 | 22 | @Override 23 | protected Hasher64 getHasherInstance() { 24 | return HASHER_INSTANCE; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/Murmur3_128GreenrobotEssentialsPerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | import org.greenrobot.essentials.hash.Murmur3F; 19 | import org.openjdk.jmh.infra.Blackhole; 20 | 21 | public class Murmur3_128GreenrobotEssentialsPerformanceTest extends AbstractPerformanceTest { 22 | 23 | @Override 24 | protected void hashObject(TestObject testObject, Blackhole blackhole) { 25 | throw new UnsupportedOperationException(); 26 | } 27 | 28 | @Override 29 | protected void hashBytesDirect(byte[] b, Blackhole blackhole) { 30 | throw new UnsupportedOperationException(); 31 | } 32 | 33 | @Override 34 | protected void hashCharsDirect(String s, Blackhole blackhole) { 35 | throw new UnsupportedOperationException(); 36 | } 37 | 38 | @Override 39 | protected void hashBytesIndirect(byte[] b, Blackhole blackhole) { 40 | Murmur3F murmur = new Murmur3F(); 41 | murmur.update(b); 42 | blackhole.consume(murmur.getValue()); 43 | } 44 | 45 | @Override 46 | protected void hashCharsIndirect(String s, Blackhole blackhole) { 47 | throw new UnsupportedOperationException(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/Murmur3_128GuavaPerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | import com.google.common.hash.HashFunction; 19 | import com.google.common.hash.Hashing; 20 | 21 | public class Murmur3_128GuavaPerformanceTest extends AbstractGuava128BitPerformanceTest { 22 | 23 | private static final HashFunction HASH_FUNCTION = Hashing.murmur3_128(); 24 | 25 | @Override 26 | protected HashFunction createHashFunction() { 27 | return HASH_FUNCTION; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/Murmur3_128PerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | public class Murmur3_128PerformanceTest extends AbstactHasher128PerformanceTest { 19 | 20 | private static final Hasher128 HASHER_INSTANCE = Hashing.murmur3_128(); 21 | 22 | @Override 23 | protected Hasher128 getHasherInstance() { 24 | return HASHER_INSTANCE; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/Murmur3_128ZeroAllocationHashingPerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | import net.openhft.hashing.LongTupleHashFunction; 19 | 20 | public class Murmur3_128ZeroAllocationHashingPerformanceTest 21 | extends AbstractZeroAllocationHashing128BitPerformanceTest { 22 | 23 | private static final LongTupleHashFunction HASH_FUNCTION = LongTupleHashFunction.murmur_3(); 24 | 25 | @Override 26 | protected LongTupleHashFunction createHashFunction() { 27 | return HASH_FUNCTION; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/Murmur3_32GreenrobotEssentialsPerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | import org.greenrobot.essentials.hash.Murmur3A; 19 | import org.openjdk.jmh.infra.Blackhole; 20 | 21 | public class Murmur3_32GreenrobotEssentialsPerformanceTest extends AbstractPerformanceTest { 22 | 23 | @Override 24 | protected void hashObject(TestObject testObject, Blackhole blackhole) { 25 | throw new UnsupportedOperationException(); 26 | } 27 | 28 | @Override 29 | protected void hashBytesDirect(byte[] b, Blackhole blackhole) { 30 | throw new UnsupportedOperationException(); 31 | } 32 | 33 | @Override 34 | protected void hashCharsDirect(String s, Blackhole blackhole) { 35 | throw new UnsupportedOperationException(); 36 | } 37 | 38 | @Override 39 | protected void hashBytesIndirect(byte[] b, Blackhole blackhole) { 40 | Murmur3A murmur = new Murmur3A(); 41 | murmur.update(b); 42 | blackhole.consume(murmur.getValue()); 43 | } 44 | 45 | @Override 46 | protected void hashCharsIndirect(String s, Blackhole blackhole) { 47 | throw new UnsupportedOperationException(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/Murmur3_32GuavaPerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | import com.google.common.hash.HashFunction; 19 | import com.google.common.hash.Hashing; 20 | 21 | public class Murmur3_32GuavaPerformanceTest extends AbstractGuava32BitPerformanceTest { 22 | private static final HashFunction HASH_FUNCTION = Hashing.murmur3_32_fixed(); 23 | 24 | @Override 25 | protected HashFunction createHashFunction() { 26 | return HASH_FUNCTION; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/Murmur3_32PerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | public class Murmur3_32PerformanceTest extends AbstactHasher32PerformanceTest { 19 | private static final Hasher32 HASHER_INSTANCE = Hashing.murmur3_32(); 20 | 21 | @Override 22 | protected Hasher32 getHasherInstance() { 23 | return HASHER_INSTANCE; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/PolymurHash2_0PerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2024 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | public class PolymurHash2_0PerformanceTest extends AbstactHasher64PerformanceTest { 19 | 20 | private static final Hasher64 HASHER_INSTANCE = 21 | Hashing.polymurHash2_0(0x2afe2c5c76d4017eL, 0x46223142eceb1893L); 22 | 23 | @Override 24 | protected Hasher64 getHasherInstance() { 25 | return HASHER_INSTANCE; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/UnorderedHashTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2024 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | import java.util.SplittableRandom; 21 | import java.util.concurrent.ThreadLocalRandom; 22 | import java.util.stream.Collectors; 23 | import org.openjdk.jmh.annotations.Benchmark; 24 | import org.openjdk.jmh.annotations.BenchmarkMode; 25 | import org.openjdk.jmh.annotations.Mode; 26 | import org.openjdk.jmh.infra.Blackhole; 27 | 28 | public class UnorderedHashTest { 29 | 30 | private static final int NUM_TEST_DATA_SETS = 100; 31 | private static final int NUM_VALUES = 1000; 32 | private static final List> TEST_DATA_LONG = new ArrayList<>(NUM_TEST_DATA_SETS); 33 | 34 | static { 35 | final SplittableRandom random = new SplittableRandom(0); 36 | for (int j = 0; j < NUM_TEST_DATA_SETS; ++j) { 37 | TEST_DATA_LONG.add(random.longs(NUM_VALUES).boxed().collect(Collectors.toList())); 38 | } 39 | } 40 | 41 | private static final HashFunnel LONG_FUNNEL = (l, h) -> h.putLong(l); 42 | 43 | private static final long long2Hash(long x) { 44 | return Hashing.murmur3_128().hashToLong(x, LONG_FUNNEL); 45 | } 46 | 47 | private static final HashFunnel> LIST_LONG_FUNNEL = 48 | (l, h) -> h.putUnorderedIterable(l, UnorderedHashTest::long2Hash); 49 | 50 | @Benchmark 51 | @BenchmarkMode(Mode.AverageTime) 52 | public void testUnordered(Blackhole blackhole) { 53 | 54 | List testData = 55 | TEST_DATA_LONG.get(ThreadLocalRandom.current().nextInt(NUM_TEST_DATA_SETS)); 56 | long hash = Hashing.murmur3_128().hashToLong(testData, LIST_LONG_FUNNEL); 57 | blackhole.consume(hash); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/WyhashFinal3PerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | public class WyhashFinal3PerformanceTest extends AbstactHasher64PerformanceTest { 19 | 20 | private static final Hasher64 HASHER_INSTANCE = Hashing.wyhashFinal3(); 21 | 22 | @Override 23 | protected Hasher64 getHasherInstance() { 24 | return HASHER_INSTANCE; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/WyhashFinal4PerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | public class WyhashFinal4PerformanceTest extends AbstactHasher64PerformanceTest { 19 | 20 | private static final Hasher64 HASHER_INSTANCE = Hashing.wyhashFinal4(); 21 | 22 | @Override 23 | protected Hasher64 getHasherInstance() { 24 | return HASHER_INSTANCE; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/XXH3_128PerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | public class XXH3_128PerformanceTest extends AbstactHasher128PerformanceTest { 19 | 20 | private static final Hasher128 HASHER_INSTANCE = Hashing.xxh3_128(); 21 | 22 | @Override 23 | protected Hasher128 getHasherInstance() { 24 | return HASHER_INSTANCE; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/XXH3_128ZeroAllocationHashingPerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | import net.openhft.hashing.LongTupleHashFunction; 19 | 20 | public class XXH3_128ZeroAllocationHashingPerformanceTest 21 | extends AbstractZeroAllocationHashing128BitPerformanceTest { 22 | 23 | private static final LongTupleHashFunction HASH_FUNCTION = LongTupleHashFunction.xx128(); 24 | 25 | @Override 26 | protected LongTupleHashFunction createHashFunction() { 27 | return HASH_FUNCTION; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/XXH3_64PerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2024 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | public class XXH3_64PerformanceTest extends AbstactHasher64PerformanceTest { 19 | 20 | private static final Hasher64 HASHER_INSTANCE = Hashing.xxh3_64(); 21 | 22 | @Override 23 | protected Hasher64 getHasherInstance() { 24 | return HASHER_INSTANCE; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/XXH3_64ZeroAllocationHashingPerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | import net.openhft.hashing.LongHashFunction; 19 | 20 | public class XXH3_64ZeroAllocationHashingPerformanceTest 21 | extends AbstractZeroAllocationHashing64BitPerformanceTest { 22 | 23 | private static final LongHashFunction HASH_FUNCTION = LongHashFunction.xx3(); 24 | 25 | @Override 26 | protected LongHashFunction createHashFunction() { 27 | return HASH_FUNCTION; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/hashing/package-info.java: -------------------------------------------------------------------------------- 1 | /** Hash algorithms */ 2 | package com.dynatrace.hash4j.hashing; 3 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/random/RandomPerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.random; 17 | 18 | import org.openjdk.jmh.annotations.*; 19 | import org.openjdk.jmh.infra.Blackhole; 20 | 21 | public class RandomPerformanceTest { 22 | @State(Scope.Thread) 23 | public static class RandomGeneratorState { 24 | public final PseudoRandomGenerator prng = 25 | PseudoRandomGeneratorProvider.splitMix64_V1().create(); 26 | } 27 | 28 | @Benchmark 29 | @BenchmarkMode(Mode.AverageTime) 30 | public void randomLong(RandomGeneratorState randomGeneratorState, Blackhole blackhole) { 31 | blackhole.consume(randomGeneratorState.prng.nextLong()); 32 | } 33 | 34 | @Benchmark 35 | @BenchmarkMode(Mode.AverageTime) 36 | public void randomInt(RandomGeneratorState randomGeneratorState, Blackhole blackhole) { 37 | blackhole.consume(randomGeneratorState.prng.nextInt()); 38 | } 39 | 40 | @Benchmark 41 | @BenchmarkMode(Mode.AverageTime) 42 | public void randomExponential(RandomGeneratorState randomGeneratorState, Blackhole blackhole) { 43 | blackhole.consume(randomGeneratorState.prng.nextExponential()); 44 | } 45 | 46 | @Benchmark 47 | @BenchmarkMode(Mode.AverageTime) 48 | public void randomDouble(RandomGeneratorState randomGeneratorState, Blackhole blackhole) { 49 | blackhole.consume(randomGeneratorState.prng.nextDouble()); 50 | } 51 | 52 | @Benchmark 53 | @BenchmarkMode(Mode.AverageTime) 54 | public void randomExponentialAlternative( 55 | RandomGeneratorState randomGeneratorState, Blackhole blackhole) { 56 | blackhole.consume(StrictMath.log1p(-randomGeneratorState.prng.nextDouble())); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/jmh/java/com/dynatrace/hash4j/similarity/SimilarityHashingPerformanceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.similarity; 17 | 18 | import com.dynatrace.hash4j.random.PseudoRandomGeneratorProvider; 19 | import java.util.SplittableRandom; 20 | import org.openjdk.jmh.annotations.*; 21 | import org.openjdk.jmh.infra.Blackhole; 22 | 23 | public class SimilarityHashingPerformanceTest { 24 | 25 | @State(Scope.Thread) 26 | public static class StateBase implements ElementHashProvider { 27 | public final SplittableRandom random = new SplittableRandom(); 28 | public final SimilarityHasher similarityHasher; 29 | 30 | @Param({"1", "10", "100", "1000", "10000", "100000"}) 31 | public int numElements; 32 | 33 | public StateBase(SimilarityHasher similarityHasher) { 34 | this.similarityHasher = similarityHasher; 35 | } 36 | 37 | public final long[] elementHashes = new long[100000]; // maximum number of elements 38 | 39 | @Override 40 | public long getElementHash(int elementIndex) { 41 | return elementHashes[elementIndex]; 42 | } 43 | 44 | @Override 45 | public int getNumberOfElements() { 46 | return numElements; 47 | } 48 | } 49 | 50 | protected void testSimilarityHashing(StateBase state, Blackhole blackhole) { 51 | for (int i = 0; i < state.numElements; ++i) { 52 | state.elementHashes[i] = state.random.nextLong(); 53 | } 54 | byte[] signature = state.similarityHasher.compute(state); 55 | blackhole.consume(signature); 56 | } 57 | 58 | protected static PseudoRandomGeneratorProvider getPseudoRandomGeneratorProvider() { 59 | return PseudoRandomGeneratorProvider.splitMix64_V1(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/consistent/ConsistentBucketHasher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.consistent; 17 | 18 | /** A hash function that maps a given hash consistently to a bucket index of given range. */ 19 | public interface ConsistentBucketHasher { 20 | 21 | /** 22 | * Returns a bucket index in the range {@code [0, numBuckets)} based on a 64-bit hash value of the 23 | * key. 24 | * 25 | *

The returned bucket index is uniformly distributed. If {@code numBuckets} is changed, 26 | * remapping to other bucket indices is minimized. 27 | * 28 | *

This function is not thread-safe! 29 | * 30 | * @param hash a 64-bit hash value of the key 31 | * @param numBuckets the number of buckets, must be positive 32 | * @return the bucket index 33 | */ 34 | int getBucket(long hash, int numBuckets); 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/consistent/ConsistentHashingUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.consistent; 17 | 18 | import static com.dynatrace.hash4j.internal.Preconditions.checkArgument; 19 | 20 | class ConsistentHashingUtil { 21 | 22 | private ConsistentHashingUtil() {} 23 | 24 | static void checkNumberOfBuckets(int numBuckets) { 25 | checkArgument(numBuckets > 0, "number of buckets must be positive"); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/consistent/package-info.java: -------------------------------------------------------------------------------- 1 | /** Consistent hash algorithms for load balancing, sharding, task distribution, etc. */ 2 | package com.dynatrace.hash4j.consistent; 3 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/distinctcount/StateChangeObserver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.distinctcount; 17 | 18 | /** 19 | * An observer of state changes of distinct counters such as {@link HyperLogLog} or {@link 20 | * UltraLogLog}. 21 | */ 22 | @FunctionalInterface 23 | public interface StateChangeObserver { 24 | 25 | /** 26 | * This method is called whenever the internal state of the approximate distinct counter has 27 | * changed. After a state change, the probability of a next state change is usually smaller. The 28 | * positive decrement of this state change probability is passed as an argument. 29 | * 30 | * @param probabilityDecrement the positive probability decrement 31 | */ 32 | void stateChanged(double probabilityDecrement); 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/distinctcount/package-info.java: -------------------------------------------------------------------------------- 1 | /** Algorithms and data structures for approximate distinct counting */ 2 | package com.dynatrace.hash4j.distinctcount; 3 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/file/AbstractFileHasher128.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.file; 17 | 18 | import com.dynatrace.hash4j.hashing.HashValue128; 19 | import java.io.File; 20 | import java.io.IOException; 21 | import java.io.InputStream; 22 | import java.nio.file.Files; 23 | import java.nio.file.Path; 24 | import java.nio.file.StandardOpenOption; 25 | 26 | abstract class AbstractFileHasher128 implements FileHasher128 { 27 | @Override 28 | public HashValue128 hashFileTo128Bits(File file) throws IOException { 29 | return hashFileTo128Bits(file.toPath()); 30 | } 31 | 32 | @Override 33 | public HashValue128 hashFileTo128Bits(Path path) throws IOException { 34 | try (InputStream fileContent = Files.newInputStream(path, StandardOpenOption.READ)) { 35 | return hashInputStreamTo128Bits(fileContent, Files.size(path)); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/file/FileHasher128.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.file; 17 | 18 | import com.dynatrace.hash4j.hashing.HashValue128; 19 | import java.io.File; 20 | import java.io.IOException; 21 | import java.io.InputStream; 22 | import java.nio.file.Path; 23 | 24 | /** A 128-bit hash function for files and input streams. */ 25 | public interface FileHasher128 { 26 | 27 | /** 28 | * Calculates a 128-bit hash value for the given file. 29 | * 30 | * @param file a file 31 | * @return the hash value 32 | * @throws IOException if an I/O error occurs 33 | */ 34 | HashValue128 hashFileTo128Bits(File file) throws IOException; 35 | 36 | /** 37 | * Calculates a 128-bit hash value for the given path. 38 | * 39 | * @param path a path 40 | * @return the hash value 41 | * @throws IOException if an I/O error occurs 42 | */ 43 | HashValue128 hashFileTo128Bits(Path path) throws IOException; 44 | 45 | /** 46 | * Calculates a 128-bit hash value for a given number of bytes of the given input stream. 47 | * 48 | * @param inputStream the input stream 49 | * @param length the length of the input stream 50 | * @return the hash value 51 | * @throws IOException if an I/O error occurs 52 | */ 53 | HashValue128 hashInputStreamTo128Bits(InputStream inputStream, long length) throws IOException; 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/file/FileHashing.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.file; 17 | 18 | /** Various implementations of hash functions for files. */ 19 | public interface FileHashing { 20 | 21 | /** 22 | * Returns a {@link FileHasher128} implementing version 1.0.2 of the Imohash algorithm using 23 | * default parameters. 24 | * 25 | *

This implementation is compatible with the Go reference implementation imohash.go. 27 | * 28 | *

For a description of the algorithm see here. 30 | * 31 | *

This algorithm does not return a uniformly distributed hash value. 32 | * 33 | * @return a file hasher instance 34 | */ 35 | static FileHasher128 imohash1_0_2() { 36 | return Imohash1_0_2.create(); 37 | } 38 | 39 | /** 40 | * Returns a {@link FileHasher128} implementing version 1.0.2 of the Imohash algorithm using 41 | * default parameters. 42 | * 43 | *

This implementation is compatible with the Go reference implementation imohash.go. 45 | * 46 | *

For a description of the algorithm and the parameters see here. 48 | * 49 | *

This algorithm does not return a uniformly distributed hash value. 50 | * 51 | * @param sampleSize the sample size 52 | * @param sampleThreshold the sample threshold 53 | * @return a file hasher instance 54 | */ 55 | static FileHasher128 imohash1_0_2(int sampleSize, long sampleThreshold) { 56 | return Imohash1_0_2.create(sampleSize, sampleThreshold); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/file/package-info.java: -------------------------------------------------------------------------------- 1 | /** Algorithms for file hashing */ 2 | package com.dynatrace.hash4j.file; 3 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/hashing/AbstractHasher128.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | interface AbstractHasher128 extends AbstractHasher64, Hasher128 { 19 | 20 | @Override 21 | default HashValue128 hashTo128Bits(T data, HashFunnel funnel) { 22 | return hashStream().put(data, funnel).get(); 23 | } 24 | 25 | @Override 26 | default HashValue128 hashBytesTo128Bits(byte[] input) { 27 | return hashBytesTo128Bits(input, 0, input.length); 28 | } 29 | 30 | @Override 31 | default long hashBytesToLong(byte[] input, int off, int len) { 32 | return hashBytesTo128Bits(input, off, len).getAsLong(); 33 | } 34 | 35 | @Override 36 | default long hashCharsToLong(CharSequence input) { 37 | return hashCharsTo128Bits(input).getAsLong(); 38 | } 39 | 40 | @Override 41 | default int getHashBitSize() { 42 | return 128; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/hashing/AbstractHasher32.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | interface AbstractHasher32 extends Hasher32, Hasher { 19 | 20 | @Override 21 | default int hashToInt(T data, HashFunnel funnel) { 22 | return hashStream().put(data, funnel).getAsInt(); 23 | } 24 | 25 | @Override 26 | default int hashBytesToInt(byte[] input) { 27 | return hashBytesToInt(input, 0, input.length); 28 | } 29 | 30 | @Override 31 | default int getHashBitSize() { 32 | return 32; 33 | } 34 | 35 | @Override 36 | default int hashLongLongToInt(long v1, long v2) { 37 | return hashStream().putLong(v1).putLong(v2).getAsInt(); 38 | } 39 | 40 | @Override 41 | default int hashLongLongLongToInt(long v1, long v2, long v3) { 42 | return hashStream().putLong(v1).putLong(v2).putLong(v3).getAsInt(); 43 | } 44 | 45 | @Override 46 | default int hashLongIntToInt(long v1, int v2) { 47 | return hashStream().putLong(v1).putInt(v2).getAsInt(); 48 | } 49 | 50 | @Override 51 | default int hashIntLongToInt(int v1, long v2) { 52 | return hashStream().putInt(v1).putLong(v2).getAsInt(); 53 | } 54 | 55 | @Override 56 | default int hashIntIntIntToInt(int v1, int v2, int v3) { 57 | return hashStream().putInt(v1).putInt(v2).putInt(v3).getAsInt(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/hashing/Hasher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | /** 19 | * A hash function. 20 | * 21 | *

Instances are immutable. Therefore, it is safe to use a single instance across multiple 22 | * threads and for multiple hash calculations. 23 | */ 24 | interface Hasher { 25 | 26 | /** 27 | * Starts a hash stream. 28 | * 29 | * @return a new {@link HashStream} instance 30 | */ 31 | HashStream hashStream(); 32 | 33 | /** 34 | * The size of the hash value in bits. 35 | * 36 | * @return the size of the hash value in bits 37 | */ 38 | int getHashBitSize(); 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/hashing/WyhashFinal3.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | class WyhashFinal3 extends AbstractWyhashFinal { 19 | 20 | private WyhashFinal3(long seedForHash, long[] secret) { 21 | super(seedForHash ^ secret[0], secret[1], secret[2], secret[3]); 22 | } 23 | 24 | @Override 25 | protected long finish(long a, long b, long seed, long len) { 26 | return wymix(secret1 ^ len, wymix(a ^ secret1, b ^ seed)); 27 | } 28 | 29 | static Hasher64 create() { 30 | return DEFAULT_HASHER_INSTANCE; 31 | } 32 | 33 | static Hasher64 create(long seedForHash) { 34 | return new WyhashFinal3(seedForHash, DEFAULT_SECRET); 35 | } 36 | 37 | static Hasher64 create(long seedForHash, long seedForSecret) { 38 | return new WyhashFinal3(seedForHash, makeSecret(seedForSecret)); 39 | } 40 | 41 | private static final Hasher64 DEFAULT_HASHER_INSTANCE = create(0L); 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/hashing/WyhashFinal4.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | import static com.dynatrace.hash4j.internal.UnsignedMultiplyUtil.unsignedMultiplyHigh; 19 | 20 | class WyhashFinal4 extends AbstractWyhashFinal { 21 | 22 | private final long secret0; 23 | 24 | private WyhashFinal4(long seedForHash, long[] secret) { 25 | super(seedForHash ^ wymix(seedForHash ^ secret[0], secret[1]), secret[1], secret[2], secret[3]); 26 | this.secret0 = secret[0]; 27 | } 28 | 29 | static Hasher64 create() { 30 | return DEFAULT_HASHER_INSTANCE; 31 | } 32 | 33 | static Hasher64 create(long seedForHash) { 34 | return new WyhashFinal4(seedForHash, DEFAULT_SECRET); 35 | } 36 | 37 | static Hasher64 create(long seedForHash, long seedForSecret) { 38 | return new WyhashFinal4(seedForHash, makeSecret(seedForSecret)); 39 | } 40 | 41 | private static final Hasher64 DEFAULT_HASHER_INSTANCE = create(0L); 42 | 43 | @Override 44 | protected long finish(long a, long b, long seed, long len) { 45 | a ^= secret1; 46 | b ^= seed; 47 | return wymix((a * b) ^ secret0 ^ len, unsignedMultiplyHigh(a, b) ^ secret1); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/hashing/package-info.java: -------------------------------------------------------------------------------- 1 | /** Hash algorithms */ 2 | package com.dynatrace.hash4j.hashing; 3 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/internal/EmptyArray.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.internal; 17 | 18 | /** Utility class defining empty arrays. */ 19 | public final class EmptyArray { 20 | 21 | private EmptyArray() {} 22 | 23 | /** An empty byte array. */ 24 | public static byte[] EMPTY_BYTE_ARRAY = {}; 25 | 26 | /** An empty short array. */ 27 | public static short[] EMPTY_SHORT_ARRAY = {}; 28 | 29 | /** An empty int array. */ 30 | public static int[] EMPTY_INT_ARRAY = {}; 31 | 32 | /** An empty long array. */ 33 | public static long[] EMPTY_LONG_ARRAY = {}; 34 | 35 | /** An empty boolean array. */ 36 | public static boolean[] EMPTY_BOOLEAN_ARRAY = {}; 37 | 38 | /** An empty float array. */ 39 | public static float[] EMPTY_FLOAT_ARRAY = {}; 40 | 41 | /** An empty double array. */ 42 | public static double[] EMPTY_DOUBLE_ARRAY = {}; 43 | 44 | /** An empty char array. */ 45 | public static char[] EMPTY_CHAR_ARRAY = {}; 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/internal/UnsignedMultiplyUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.internal; 17 | 18 | /** Utility class for the unsigned multiplication of {@code long} values. */ 19 | public final class UnsignedMultiplyUtil { 20 | 21 | private UnsignedMultiplyUtil() {} 22 | 23 | /** 24 | * Returns the most significant 64 bits of the unsigned 128-bit product of two unsigned 64-bit 25 | * factors as a long. 26 | * 27 | * @param x the first value 28 | * @param y the second value 29 | * @return the result 30 | */ 31 | public static long unsignedMultiplyHigh(long x, long y) { 32 | return Math.multiplyHigh(x, y) + ((x >> 63) & y) + ((y >> 63) & x); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/internal/package-info.java: -------------------------------------------------------------------------------- 1 | /** Helper classes. */ 2 | package com.dynatrace.hash4j.internal; 3 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/random/AbstractPseudoRandomGenerator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.random; 17 | 18 | abstract class AbstractPseudoRandomGenerator implements PseudoRandomGenerator { 19 | 20 | @Override 21 | public int nextInt() { 22 | return (int) nextLong(); 23 | } 24 | 25 | // see algorithm 5 with L=32 in Lemire, Daniel. "Fast random integer generation in an interval." 26 | // ACM Transactions on Modeling and Computer Simulation (TOMACS) 29.1 (2019): 1-12. 27 | @Override 28 | public int uniformInt(int exclusiveUpperBound) { 29 | long s = exclusiveUpperBound; 30 | long x = nextInt() & 0xFFFFFFFFL; 31 | long m = x * s; // is always positive as 0 <= s < 2^31 and 0 <= x < 2^32 => 0 <= m < 2^63 32 | long l = m & 0xFFFFFFFFL; 33 | if (l < s) { 34 | long t = 0x100000000L % s; 35 | while (l < t) { 36 | x = nextInt() & 0xFFFFFFFFL; 37 | m = x * s; // is always positive as 0 <= s < 2^31 and 0 <= x < 2^32 => 0 <= m < 2^63 38 | l = m & 0xFFFFFFFFL; 39 | } 40 | } 41 | return (int) (m >>> 32); 42 | } 43 | 44 | @Override 45 | public double nextDouble() { 46 | return (nextLong() >>> 11) * 0x1.0p-53; 47 | } 48 | 49 | @Override 50 | public double nextExponential() { 51 | return RandomExponentialUtil.exponential(this); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/random/PseudoRandomGenerator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.random; 17 | 18 | /** A pseudo-random generator. */ 19 | public interface PseudoRandomGenerator { 20 | 21 | /** 22 | * Returns a random uniformly distributed 64-bit {@code long} value. 23 | * 24 | * @return a random value 25 | */ 26 | long nextLong(); 27 | 28 | /** 29 | * Returns a random uniformly distributed 32-bit {@code int} value. 30 | * 31 | * @return a random value 32 | */ 33 | int nextInt(); 34 | 35 | /** 36 | * Returns a random uniformly distributed 32-bit {code int} value greater than or equal to 0 and 37 | * less than the given upper bound. 38 | * 39 | *

The behavior is undefined, if the given upper bound is non-positive. 40 | * 41 | * @param exclusiveBound the (exclusive) upper bound (must be positve) 42 | * @return a random value 43 | */ 44 | int uniformInt(int exclusiveBound); 45 | 46 | /** 47 | * Resets the pseudo-random generator using the given 64-bit seed value. 48 | * 49 | * @param seed the seed value 50 | * @return this 51 | */ 52 | PseudoRandomGenerator reset(long seed); 53 | 54 | /** 55 | * Returns a random uniformly distributed {@code double} value in the range [0, 1). 56 | * 57 | * @return a random value 58 | */ 59 | double nextDouble(); 60 | 61 | /** 62 | * Returns an exponentially distributed {@code double} value with mean 1. 63 | * 64 | * @return a random value 65 | */ 66 | double nextExponential(); 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/random/PseudoRandomGeneratorProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.random; 17 | 18 | /** A provider for pseudo-random generators. */ 19 | public interface PseudoRandomGeneratorProvider { 20 | 21 | /** 22 | * Creates a new {@link PseudoRandomGenerator} instance. 23 | * 24 | * @return the new pseudo-random generator instance 25 | */ 26 | PseudoRandomGenerator create(); 27 | 28 | /** 29 | * Creates a new {@link PseudoRandomGenerator} instance and sets a seed. 30 | * 31 | * @param seed the seed value 32 | * @return the new pseudo-random generator instance 33 | */ 34 | default PseudoRandomGenerator create(long seed) { 35 | return create().reset(seed); 36 | } 37 | 38 | /** 39 | * Returns a {@link PseudoRandomGeneratorProvider} based on the SplitMix64 algorithm. 40 | * 41 | * @return a {@link PseudoRandomGeneratorProvider} 42 | */ 43 | static PseudoRandomGeneratorProvider splitMix64_V1() { 44 | return SplitMix64V1::new; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/random/SplitMix64V1.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* 18 | * The implementation in this file is based on the implementation published 19 | * at https://prng.di.unimi.it/splitmix64.c under the following license: 20 | * 21 | * Written in 2015 by Sebastiano Vigna (vigna@acm.org) 22 | * 23 | * To the extent possible under law, the author has dedicated all copyright 24 | * and related and neighboring rights to this software to the public domain 25 | * worldwide. This software is distributed without any warranty. 26 | * 27 | * See . 28 | */ 29 | package com.dynatrace.hash4j.random; 30 | 31 | final class SplitMix64V1 extends AbstractPseudoRandomGenerator { 32 | 33 | private long state; 34 | 35 | SplitMix64V1() {} 36 | 37 | @Override 38 | public long nextLong() { 39 | state += 0x9e3779b97f4a7c15L; 40 | long z = state; 41 | z = (z ^ (z >>> 30)) * 0xbf58476d1ce4e5b9L; 42 | z = (z ^ (z >>> 27)) * 0x94d049bb133111ebL; 43 | return z ^ (z >>> 31); 44 | } 45 | 46 | @Override 47 | public SplitMix64V1 reset(long seed) { 48 | this.state = seed; 49 | return this; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/random/package-info.java: -------------------------------------------------------------------------------- 1 | /** Algorithms for pseudo-random number generation */ 2 | package com.dynatrace.hash4j.random; 3 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/similarity/FastSimHashVersion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.similarity; 17 | 18 | import com.dynatrace.hash4j.random.PseudoRandomGeneratorProvider; 19 | 20 | /** Versions of FastSimHash implementations. */ 21 | public enum FastSimHashVersion { 22 | /** 23 | * Default version. 24 | * 25 | *

Not stable! Use concrete version if compatibility is important, if for example hash 26 | * signatures are persisted. 27 | */ 28 | DEFAULT { 29 | @Override 30 | SimilarityHashPolicy create(int numberOfComponents) { 31 | return new FastSimHashPolicy_v1( 32 | numberOfComponents, PseudoRandomGeneratorProvider.splitMix64_V1()); 33 | } 34 | }, 35 | /** Version 1. */ 36 | V1 { 37 | @Override 38 | SimilarityHashPolicy create(int numberOfComponents) { 39 | return new FastSimHashPolicy_v1( 40 | numberOfComponents, PseudoRandomGeneratorProvider.splitMix64_V1()); 41 | } 42 | }; 43 | 44 | abstract SimilarityHashPolicy create(int numberOfComponents); 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/similarity/MinHashVersion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.similarity; 17 | 18 | import com.dynatrace.hash4j.random.PseudoRandomGeneratorProvider; 19 | 20 | /** Versions of MinHash implementations. */ 21 | public enum MinHashVersion { 22 | /** 23 | * Default version. 24 | * 25 | *

Not stable! Use concrete version if compatibility is important, if for example hash 26 | * signatures are persisted. 27 | */ 28 | DEFAULT { 29 | @Override 30 | SimilarityHashPolicy create(int numberOfComponents, int bitsPerComponent) { 31 | return new MinHashPolicy_v1( 32 | numberOfComponents, bitsPerComponent, PseudoRandomGeneratorProvider.splitMix64_V1()); 33 | } 34 | }, 35 | /** Version 1. */ 36 | V1 { 37 | @Override 38 | SimilarityHashPolicy create(int numberOfComponents, int bitsPerComponent) { 39 | return new MinHashPolicy_v1( 40 | numberOfComponents, bitsPerComponent, PseudoRandomGeneratorProvider.splitMix64_V1()); 41 | } 42 | }; 43 | 44 | abstract SimilarityHashPolicy create(int numberOfComponents, int bitsPerComponent); 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/similarity/SimHashVersion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.similarity; 17 | 18 | import com.dynatrace.hash4j.random.PseudoRandomGeneratorProvider; 19 | 20 | /** Versions of FastSimHash implementations. */ 21 | public enum SimHashVersion { 22 | /** 23 | * Default version. 24 | * 25 | *

Not stable! Use concrete version if compatibility is important, if for example hash 26 | * signatures are persisted. 27 | */ 28 | DEFAULT { 29 | @Override 30 | SimilarityHashPolicy create(int numberOfComponents) { 31 | return new SimHashPolicy_v1( 32 | numberOfComponents, PseudoRandomGeneratorProvider.splitMix64_V1()); 33 | } 34 | }, 35 | /** Version 1. */ 36 | V1 { 37 | @Override 38 | SimilarityHashPolicy create(int numberOfComponents) { 39 | return new SimHashPolicy_v1( 40 | numberOfComponents, PseudoRandomGeneratorProvider.splitMix64_V1()); 41 | } 42 | }; 43 | 44 | abstract SimilarityHashPolicy create(int numberOfComponents); 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/similarity/SimilarityHasher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.similarity; 17 | 18 | /** 19 | * A hasher that is able to compute hash signatures which can be used for similarity estimations. 20 | */ 21 | public interface SimilarityHasher { 22 | 23 | /** 24 | * Computes a hash signature for a given collection of 64-bit element hash values provided by the 25 | * given element hash provider. 26 | * 27 | * @param elementHashProvider the element hash provider 28 | * @return the hash signature 29 | */ 30 | byte[] compute(ElementHashProvider elementHashProvider); 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/similarity/SuperMinHashVersion.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.similarity; 17 | 18 | import com.dynatrace.hash4j.random.PseudoRandomGeneratorProvider; 19 | 20 | /** Versions of SuperMinHash implementations. */ 21 | public enum SuperMinHashVersion { 22 | /** 23 | * Default version. 24 | * 25 | *

Not stable! Use concrete version if compatibility is important, if for example hash 26 | * signatures are persisted. 27 | */ 28 | DEFAULT { 29 | @Override 30 | SimilarityHashPolicy create(int numberOfComponents, int bitsPerComponent) { 31 | return new SuperMinHashPolicy_v1( 32 | numberOfComponents, bitsPerComponent, PseudoRandomGeneratorProvider.splitMix64_V1()); 33 | } 34 | }, 35 | /** Version 1. */ 36 | V1 { 37 | @Override 38 | SimilarityHashPolicy create(int numberOfComponents, int bitsPerComponent) { 39 | return new SuperMinHashPolicy_v1( 40 | numberOfComponents, bitsPerComponent, PseudoRandomGeneratorProvider.splitMix64_V1()); 41 | } 42 | }; 43 | 44 | abstract SimilarityHashPolicy create(int numberOfComponents, int bitsPerComponent); 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/similarity/package-info.java: -------------------------------------------------------------------------------- 1 | /** Algorithms for similarity hashing */ 2 | package com.dynatrace.hash4j.similarity; 3 | -------------------------------------------------------------------------------- /src/main/java/com/dynatrace/hash4j/util/package-info.java: -------------------------------------------------------------------------------- 1 | /** Utilities */ 2 | package com.dynatrace.hash4j.util; 3 | -------------------------------------------------------------------------------- /src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | /** Hash4j */ 2 | module hash4j { 3 | exports com.dynatrace.hash4j.consistent; 4 | exports com.dynatrace.hash4j.distinctcount; 5 | exports com.dynatrace.hash4j.file; 6 | exports com.dynatrace.hash4j.hashing; 7 | exports com.dynatrace.hash4j.random; 8 | exports com.dynatrace.hash4j.similarity; 9 | exports com.dynatrace.hash4j.util; 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java21/com/dynatrace/hash4j/internal/UnsignedMultiplyUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.internal; 17 | 18 | /** Utility class for the unsigned multiplication of {@code long} values. */ 19 | public final class UnsignedMultiplyUtil { 20 | 21 | private UnsignedMultiplyUtil() {} 22 | 23 | /** 24 | * Returns the most significant 64 bits of the unsigned 128-bit product of two unsigned 64-bit 25 | * factors as a long. 26 | * 27 | * @param x the first value 28 | * @param y the second value 29 | * @return the result 30 | */ 31 | public static long unsignedMultiplyHigh(long x, long y) { 32 | return Math.unsignedMultiplyHigh(x, y); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/com/dynatrace/hash4j/consistent/ConsistentHashingUtilTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.consistent; 17 | 18 | import static com.dynatrace.hash4j.consistent.ConsistentHashingUtil.checkNumberOfBuckets; 19 | import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; 20 | import static org.assertj.core.api.Assertions.assertThatNoException; 21 | 22 | import org.junit.jupiter.api.Test; 23 | 24 | class ConsistentHashingUtilTest { 25 | 26 | @Test 27 | void testCheckNumberOfBuckets() { 28 | assertThatIllegalArgumentException().isThrownBy(() -> checkNumberOfBuckets(0)); 29 | assertThatIllegalArgumentException().isThrownBy(() -> checkNumberOfBuckets(-1)); 30 | assertThatIllegalArgumentException().isThrownBy(() -> checkNumberOfBuckets(Integer.MIN_VALUE)); 31 | assertThatNoException().isThrownBy(() -> checkNumberOfBuckets(1)); 32 | assertThatNoException().isThrownBy(() -> checkNumberOfBuckets(2)); 33 | assertThatNoException().isThrownBy(() -> checkNumberOfBuckets(Integer.MAX_VALUE)); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/com/dynatrace/hash4j/consistent/ConsistentJumpBackBucketHasherTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023-2024 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.consistent; 17 | 18 | import com.dynatrace.hash4j.random.PseudoRandomGeneratorProvider; 19 | 20 | class ConsistentJumpBackBucketHasherTest extends AbstractConsistentBucketHasherTest { 21 | 22 | @Override 23 | protected ConsistentBucketHasher getConsistentBucketHasher( 24 | PseudoRandomGeneratorProvider pseudoRandomGeneratorProvider) { 25 | return ConsistentHashing.jumpBackHash(pseudoRandomGeneratorProvider); 26 | } 27 | 28 | @Override 29 | protected long getCheckSum() { 30 | return 0x23d7a0d288cd67e7L; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/com/dynatrace/hash4j/consistent/ConsistentJumpBucketHasherTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.consistent; 17 | 18 | import static org.assertj.core.api.Assertions.*; 19 | 20 | import com.dynatrace.hash4j.random.PseudoRandomGeneratorProvider; 21 | 22 | class ConsistentJumpBucketHasherTest extends AbstractConsistentBucketHasherTest { 23 | 24 | @Override 25 | protected ConsistentBucketHasher getConsistentBucketHasher( 26 | PseudoRandomGeneratorProvider pseudoRandomGeneratorProvider) { 27 | return ConsistentHashing.jumpHash(pseudoRandomGeneratorProvider); 28 | } 29 | 30 | @Override 31 | protected long getCheckSum() { 32 | return 0xfd5390c955b998f7L; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/com/dynatrace/hash4j/distinctcount/BigIntTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.distinctcount; 17 | 18 | import static org.assertj.core.api.Assertions.assertThat; 19 | 20 | import java.math.BigInteger; 21 | import org.junit.jupiter.api.Test; 22 | 23 | class BigIntTest { 24 | 25 | @Test 26 | void testBigIntFloor() { 27 | assertThat(BigInt.floor(1.2)).hasToString("1"); 28 | assertThat(BigInt.floor(1e20)).hasToString("100000000000000000000"); 29 | assertThat(BigInt.floor(1e30)).hasToString("1000000000000000019884624838656"); 30 | } 31 | 32 | @Test 33 | void testBigIntCeil() { 34 | assertThat(BigInt.ceil(1.2)).hasToString("2"); 35 | assertThat(BigInt.ceil(1e20)).hasToString("100000000000000000000"); 36 | assertThat(BigInt.ceil(1e30)).hasToString("1000000000000000019884624838656"); 37 | } 38 | 39 | @Test 40 | void testIncrement() { 41 | BigInt i = BigInt.ceil(1); 42 | i.increment(); 43 | assertThat(i).hasToString("2"); 44 | } 45 | 46 | @Test 47 | void testDecrement() { 48 | BigInt i = BigInt.ceil(Math.pow(2, 63)); 49 | i.decrement(); 50 | assertThat(i).hasToString(Long.toString(Long.MAX_VALUE)); 51 | } 52 | 53 | @Test 54 | void testAdd() { 55 | BigInt i1 = BigInt.fromBigInt(new BigInteger("10000500000000005")); 56 | BigInt i2 = BigInt.fromBigInt(new BigInteger("10000900000000006")); 57 | i1.add(i2); 58 | assertThat(i1).hasToString("20001400000000011"); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/test/java/com/dynatrace/hash4j/distinctcount/ConversionDemo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.distinctcount; 17 | 18 | import static org.assertj.core.api.Assertions.assertThat; 19 | 20 | import com.dynatrace.hash4j.hashing.Hasher64; 21 | import com.dynatrace.hash4j.hashing.Hashing; 22 | import org.junit.jupiter.api.Test; 23 | 24 | class ConversionDemo { 25 | 26 | @Test 27 | void demoUltraLogLogToHyperLogLogConversion() { 28 | 29 | Hasher64 hasher = Hashing.komihash5_0(); 30 | 31 | HyperLogLog hllSketch = HyperLogLog.create(12); 32 | UltraLogLog ullSketch = UltraLogLog.create(12); 33 | 34 | hllSketch.add(hasher.hashCharsToLong("foo")); 35 | hllSketch.add(hasher.hashCharsToLong("bar")); 36 | hllSketch.add(hasher.hashCharsToLong("foo")); 37 | 38 | ullSketch.add(hasher.hashCharsToLong("foo")); 39 | ullSketch.add(hasher.hashCharsToLong("bar")); 40 | ullSketch.add(hasher.hashCharsToLong("foo")); 41 | 42 | HyperLogLog hllSketchConvertedFromUllSketch = HyperLogLog.create(ullSketch); 43 | 44 | assertThat(hllSketchConvertedFromUllSketch.getState()).isEqualTo(hllSketch.getState()); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/com/dynatrace/hash4j/distinctcount/TestUtilsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.distinctcount; 17 | 18 | import static org.assertj.core.api.Assertions.assertThat; 19 | 20 | import java.util.List; 21 | import java.util.stream.Collectors; 22 | import java.util.stream.IntStream; 23 | import org.junit.jupiter.api.Test; 24 | 25 | class TestUtilsTest { 26 | 27 | @Test 28 | void testGetDistinctCountValues() { 29 | List list = TestUtils.getDistinctCountValues(1e3, 0.5); 30 | List actual = list.stream().map(BigInt::toString).collect(Collectors.toList()); 31 | List expected = 32 | IntStream.of(1, 2, 3, 4, 6, 8, 12, 18, 27, 40, 59, 88, 132, 198, 297, 445, 667, 1000) 33 | .mapToObj(Integer::toString) 34 | .collect(Collectors.toList()); 35 | assertThat(actual).isEqualTo(expected); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/test/java/com/dynatrace/hash4j/file/FileHashingDemo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023-2024 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.file; 17 | 18 | import static org.assertj.core.api.Assertions.assertThat; 19 | 20 | import com.dynatrace.hash4j.hashing.HashValue128; 21 | import java.io.File; 22 | import java.io.FileWriter; 23 | import java.io.IOException; 24 | import java.nio.charset.StandardCharsets; 25 | import java.nio.file.Path; 26 | import org.junit.jupiter.api.Test; 27 | import org.junit.jupiter.api.io.TempDir; 28 | 29 | class FileHashingDemo { 30 | 31 | @Test 32 | void demoImohash(@TempDir Path path) throws IOException { 33 | 34 | // create some file in the given path 35 | File file = path.resolve("test.txt").toFile(); 36 | try (FileWriter fileWriter = new FileWriter(file, StandardCharsets.UTF_8)) { 37 | fileWriter.write("this is the file content"); 38 | } 39 | 40 | // use ImoHash to hash that file 41 | HashValue128 hash = FileHashing.imohash1_0_2().hashFileTo128Bits(file); 42 | // returns 0xd317f2dad6ea7ae56ff7fdb517e33918 43 | 44 | assertThat(hash).hasToString("0xd317f2dad6ea7ae56ff7fdb517e33918"); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/com/dynatrace/hash4j/hashing/AbstractHashStreamCompatibilityTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | import static org.assertj.core.api.Assertions.assertThat; 19 | 20 | import org.junit.jupiter.api.Test; 21 | 22 | class AbstractHashStreamCompatibilityTest { 23 | 24 | @Test 25 | void testHashCompatibility() { 26 | 27 | HashValue128 hash128 = new HashValue128(0x4cdfea92fccec3ffL, 0x85e6a3b83eb8873aL); 28 | AbstractHashStream128 calculator = 29 | new AbstractHashStream128() { 30 | 31 | @Override 32 | public HashStream128 putByte(byte v) { 33 | return this; 34 | } 35 | 36 | @Override 37 | public HashStream128 reset() { 38 | return this; 39 | } 40 | 41 | @Override 42 | public HashStream128 copy() { 43 | throw new UnsupportedOperationException(); 44 | } 45 | 46 | @Override 47 | public Hasher128 getHasher() { 48 | throw new UnsupportedOperationException(); 49 | } 50 | 51 | @Override 52 | public int getHashBitSize() { 53 | return 128; 54 | } 55 | 56 | @Override 57 | public HashValue128 get() { 58 | return hash128; 59 | } 60 | }; 61 | 62 | assertThat(calculator.getAsInt()).isEqualTo(hash128.getAsInt()); 63 | assertThat(calculator.getAsLong()).isEqualTo(hash128.getAsLong()); 64 | assertThat(calculator.get()).isEqualTo(hash128); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/test/java/com/dynatrace/hash4j/hashing/HashValuesTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | import static org.assertj.core.api.Assertions.assertThat; 19 | 20 | import org.junit.jupiter.api.Test; 21 | 22 | class HashValuesTest { 23 | 24 | @Test 25 | void testToHexStringAndToByteArray() { 26 | 27 | HashValue128 hashValue128 = new HashValue128(0xf0e1d2c3b4a59687L, 0x78695a4b3c2d1e0fL); 28 | long hashValue64 = 0x78695a4b3c2d1e0fL; 29 | int hashValue32 = 0x3c2d1e0f; 30 | 31 | assertThat(hashValue128.getAsLong()).isEqualTo(hashValue64); 32 | assertThat(hashValue128.getAsInt()).isEqualTo(hashValue32); 33 | assertThat((int) hashValue64).isEqualTo(hashValue32); 34 | 35 | assertThat(HashValues.toHexString(hashValue128)).isEqualTo("f0e1d2c3b4a5968778695a4b3c2d1e0f"); 36 | assertThat(HashValues.toHexString(hashValue64)).isEqualTo("78695a4b3c2d1e0f"); 37 | assertThat(HashValues.toHexString(hashValue32)).isEqualTo("3c2d1e0f"); 38 | 39 | assertThat(Long.toHexString(hashValue64)).isEqualTo("78695a4b3c2d1e0f"); 40 | assertThat(Long.toHexString(hashValue32)).isEqualTo("3c2d1e0f"); 41 | 42 | assertThat(HashValues.toByteArray(hashValue128)) 43 | .containsExactly( 44 | 0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69, 0x78, 0x87, 0x96, 0xa5, 0xb4, 0xc3, 0xd2, 45 | 0xe1, 0xf0); 46 | assertThat(HashValues.toByteArray(hashValue64)) 47 | .containsExactly(0x0f, 0x1e, 0x2d, 0x3c, 0x4b, 0x5a, 0x69, 0x78); 48 | assertThat(HashValues.toByteArray(hashValue32)).containsExactly(0x0f, 0x1e, 0x2d, 0x3c); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/test/java/com/dynatrace/hash4j/hashing/TestHashStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.hashing; 17 | 18 | import java.util.Arrays; 19 | import java.util.Objects; 20 | 21 | class TestHashStream implements AbstractHashStream { 22 | private int size = 0; 23 | private byte[] data = new byte[1]; 24 | 25 | @Override 26 | public HashStream putByte(byte v) { 27 | if (size == data.length) { 28 | data = Arrays.copyOf(data, data.length * 2); 29 | } 30 | data[size] = v; 31 | size += 1; 32 | return this; 33 | } 34 | 35 | @Override 36 | public HashStream reset() { 37 | size = 0; 38 | return this; 39 | } 40 | 41 | @Override 42 | public TestHashStream copy() { 43 | final TestHashStream hashStream = new TestHashStream(); 44 | hashStream.size = size; 45 | System.arraycopy(data, 0, hashStream.data, 0, data.length); 46 | return hashStream; 47 | } 48 | 49 | @Override 50 | public Hasher getHasher() { 51 | throw new UnsupportedOperationException(); 52 | } 53 | 54 | @Override 55 | public int getHashBitSize() { 56 | throw new UnsupportedOperationException(); 57 | } 58 | 59 | @Override 60 | public boolean equals(Object o) { 61 | if (this == o) return true; 62 | if (!(o instanceof TestHashStream)) return false; 63 | TestHashStream that = (TestHashStream) o; 64 | return size == that.size && Arrays.equals(data, that.data); 65 | } 66 | 67 | public byte[] getData() { 68 | return Arrays.copyOf(data, size); 69 | } 70 | 71 | @Override 72 | public int hashCode() { 73 | int result = Objects.hash(size); 74 | result = 31 * result + Arrays.hashCode(data); 75 | return result; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/test/java/com/dynatrace/hash4j/internal/PreconditionsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.internal; 17 | 18 | import static com.dynatrace.hash4j.internal.Preconditions.checkArgument; 19 | import static com.dynatrace.hash4j.internal.Preconditions.checkState; 20 | import static org.assertj.core.api.Assertions.*; 21 | 22 | import org.junit.jupiter.api.Test; 23 | 24 | class PreconditionsTest { 25 | 26 | @Test 27 | void testCheckArgument() { 28 | assertThatNoException().isThrownBy(() -> checkArgument(true)); 29 | assertThatIllegalArgumentException().isThrownBy(() -> checkArgument(false)); 30 | } 31 | 32 | @Test 33 | void testCheckArgumentWithErrorMessage() { 34 | String msg = "msg"; 35 | assertThatNoException().isThrownBy(() -> checkArgument(true, msg)); 36 | assertThatIllegalArgumentException() 37 | .isThrownBy(() -> checkArgument(false, msg)) 38 | .withMessage(msg); 39 | } 40 | 41 | @Test 42 | void testCheckArgumentWithErrorMessageAndLongValue() { 43 | long value = 123; 44 | String msgPrefix = "abc"; 45 | String msgPostfix = "xyz"; 46 | String msgFormatString = msgPrefix + "%d" + msgPostfix; 47 | String expectedMsg = msgPrefix + value + msgPostfix; 48 | assertThatNoException().isThrownBy(() -> checkArgument(true, msgFormatString, value)); 49 | assertThatIllegalArgumentException() 50 | .isThrownBy(() -> checkArgument(false, msgFormatString, value)) 51 | .withMessage(expectedMsg); 52 | } 53 | 54 | @Test 55 | void testCheckState() { 56 | assertThatNoException().isThrownBy(() -> checkState(true)); 57 | assertThatIllegalStateException().isThrownBy(() -> checkState(false)); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/test/java/com/dynatrace/hash4j/internal/UnsignedMultiplyUtilTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.internal; 17 | 18 | import static org.assertj.core.api.Assertions.assertThat; 19 | 20 | import java.util.SplittableRandom; 21 | import org.junit.jupiter.api.Test; 22 | 23 | class UnsignedMultiplyUtilTest { 24 | 25 | @Test 26 | void testUnsignedMultiply() { 27 | SplittableRandom random = new SplittableRandom(0L); 28 | int n = 10000; 29 | long checkSum = 0; 30 | for (int i = 0; i < n; ++i) { 31 | checkSum += UnsignedMultiplyUtil.unsignedMultiplyHigh(random.nextLong(), random.nextLong()); 32 | } 33 | assertThat(checkSum).isEqualTo(0xab0a08649b745db7L); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/com/dynatrace/hash4j/random/AbstractPseudoRandomGeneratorProviderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.random; 17 | 18 | import org.assertj.core.api.Assertions; 19 | import org.junit.jupiter.api.Test; 20 | 21 | public abstract class AbstractPseudoRandomGeneratorProviderTest { 22 | 23 | protected abstract PseudoRandomGeneratorProvider getPseudoRandomGeneratorProvider(); 24 | 25 | @Test 26 | void testCreateWithSeed() { 27 | long seed = 0x668914708c9e7635L; 28 | Assertions.assertThat(getPseudoRandomGeneratorProvider().create(seed).nextLong()) 29 | .isEqualTo(getPseudoRandomGeneratorProvider().create().reset(seed).nextLong()); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/com/dynatrace/hash4j/random/SplitMix64_v1ProviderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.random; 17 | 18 | public class SplitMix64_v1ProviderTest extends AbstractPseudoRandomGeneratorProviderTest { 19 | @Override 20 | protected PseudoRandomGeneratorProvider getPseudoRandomGeneratorProvider() { 21 | return PseudoRandomGeneratorProvider.splitMix64_V1(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/com/dynatrace/hash4j/random/SplitMix64_v1Test.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.random; 17 | 18 | import static org.assertj.core.api.Assertions.assertThat; 19 | 20 | import java.util.SplittableRandom; 21 | import org.hipparchus.random.RandomGenerator; 22 | import org.hipparchus.random.Well1024a; 23 | import org.junit.jupiter.api.Test; 24 | 25 | class SplitMix64_v1Test extends AbstractPseudoRandomGeneratorTest { 26 | 27 | @Test 28 | void testConsistency() { 29 | 30 | RandomGenerator rng = new Well1024a(0x321f290dee3d921dL); 31 | 32 | int numIterations = 100; 33 | int numValuesPerIterations = 10; 34 | 35 | for (int i = 0; i < numIterations; ++i) { 36 | long seed = rng.nextLong(); 37 | 38 | SplittableRandom splittableRandom = new SplittableRandom(seed); 39 | PseudoRandomGenerator pseudoRandomGenerator = createPseudoRandomGenerator(); 40 | pseudoRandomGenerator.reset(seed); 41 | 42 | for (int j = 0; j < numValuesPerIterations; ++j) { 43 | long actual = pseudoRandomGenerator.nextLong(); 44 | long expected = splittableRandom.nextLong(); 45 | assertThat(actual).isEqualTo(expected); 46 | } 47 | } 48 | } 49 | 50 | @Override 51 | protected PseudoRandomGenerator createPseudoRandomGenerator() { 52 | return new SplitMix64V1(); 53 | } 54 | 55 | @Override 56 | protected long getExpectedStabilityCheckSum() { 57 | return 0x8d81600546698168L; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/test/java/com/dynatrace/hash4j/similarity/AbstractMinHashPolicyTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.similarity; 17 | 18 | import static org.assertj.core.api.Assertions.assertThat; 19 | import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; 20 | 21 | import org.junit.jupiter.api.Test; 22 | 23 | abstract class AbstractMinHashPolicyTest extends AbstractSimilarityHasherPolicyTest { 24 | 25 | @Override 26 | protected final SimilarityHashPolicy getSimilarityHashPolicy(int numberOfComponents) { 27 | return getSimilarityHashPolicy(numberOfComponents, 1); 28 | } 29 | 30 | protected abstract SimilarityHashPolicy getSimilarityHashPolicy( 31 | int numberOfComponents, int bitsPerComponent); 32 | 33 | @Test 34 | void testInvalidBitsPerComponent() { 35 | assertThatIllegalArgumentException().isThrownBy(() -> getSimilarityHashPolicy(5, -1)); 36 | assertThatIllegalArgumentException().isThrownBy(() -> getSimilarityHashPolicy(5, 0)); 37 | assertThatIllegalArgumentException().isThrownBy(() -> getSimilarityHashPolicy(5, 65)); 38 | } 39 | 40 | @Test 41 | void testGetComponentSizeInBits() { 42 | for (int bitsPerComponent = 1; bitsPerComponent <= 64; ++bitsPerComponent) { 43 | SimilarityHashPolicy policy = getSimilarityHashPolicy(3, bitsPerComponent); 44 | assertThat(policy.getComponentSizeInBits()).isEqualTo(bitsPerComponent); 45 | } 46 | } 47 | 48 | @Override 49 | protected double calculateExpectedMatchProbability( 50 | long intersectionSize, long difference1Size, long difference2Size) { 51 | long unionSize = intersectionSize + difference1Size + difference2Size; 52 | double expectedJaccardSimilarity = intersectionSize / (double) unionSize; 53 | return (1. + expectedJaccardSimilarity) * 0.5; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/test/java/com/dynatrace/hash4j/similarity/ElementHashProviderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022-2023 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.similarity; 17 | 18 | import static org.assertj.core.api.Assertions.*; 19 | 20 | import java.util.Collections; 21 | import org.junit.jupiter.api.Test; 22 | 23 | class ElementHashProviderTest { 24 | 25 | @Test 26 | void testNullArray() { 27 | assertThatNullPointerException().isThrownBy(() -> ElementHashProvider.ofValues(null)); 28 | } 29 | 30 | @Test 31 | void testEmpty() { 32 | assertThatIllegalArgumentException().isThrownBy(() -> ElementHashProvider.ofValues()); 33 | assertThatIllegalArgumentException() 34 | .isThrownBy(() -> ElementHashProvider.ofCollection(Collections.emptySet(), x -> 0)); 35 | } 36 | 37 | @Test 38 | void testNullFunction() { 39 | assertThatNullPointerException().isThrownBy(() -> ElementHashProvider.ofFunction(null, 5)); 40 | assertThatNullPointerException() 41 | .isThrownBy(() -> ElementHashProvider.ofCollection(null, x -> 0)); 42 | assertThatNullPointerException() 43 | .isThrownBy(() -> ElementHashProvider.ofCollection(Collections.emptySet(), null)); 44 | } 45 | 46 | @Test 47 | void testFunctionWithInvalidNumberOfElements() { 48 | assertThatIllegalArgumentException() 49 | .isThrownBy(() -> ElementHashProvider.ofFunction(i -> i, 0)); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/com/dynatrace/hash4j/similarity/MinHashVersionTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.similarity; 17 | 18 | import static org.assertj.core.api.Assertions.assertThat; 19 | 20 | import org.junit.jupiter.api.Test; 21 | 22 | class MinHashVersionTest { 23 | 24 | @Test 25 | void testConstants() { 26 | assertThat(MinHashVersion.DEFAULT.create(3, 5)).isInstanceOf(MinHashPolicy_v1.class); 27 | assertThat(MinHashVersion.V1.create(3, 5)).isInstanceOf(MinHashPolicy_v1.class); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/com/dynatrace/hash4j/similarity/SuperMinHashPolicy_v1aTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.similarity; 17 | 18 | import com.dynatrace.hash4j.random.PseudoRandomGeneratorProvider; 19 | 20 | public class SuperMinHashPolicy_v1aTest extends AbstractSuperMinHashPolicyTest { 21 | 22 | @Override 23 | protected SimilarityHashPolicy getSimilarityHashPolicy( 24 | int numberOfComponents, int bitsPerComponent) { 25 | return new SuperMinHashPolicy_v1a( 26 | numberOfComponents, bitsPerComponent, PseudoRandomGeneratorProvider.splitMix64_V1()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/com/dynatrace/hash4j/similarity/SuperMinHashPolicy_v1bTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.similarity; 17 | 18 | import static org.assertj.core.api.Assertions.assertThat; 19 | 20 | import com.dynatrace.hash4j.random.PseudoRandomGeneratorProvider; 21 | import org.junit.jupiter.api.Test; 22 | 23 | class SuperMinHashPolicy_v1bTest extends AbstractSuperMinHashPolicyTest { 24 | 25 | @Override 26 | protected SimilarityHashPolicy getSimilarityHashPolicy( 27 | int numberOfComponents, int bitsPerComponent) { 28 | return new SuperMinHashPolicy_v1b( 29 | numberOfComponents, bitsPerComponent, PseudoRandomGeneratorProvider.splitMix64_V1()); 30 | } 31 | 32 | @Test 33 | void testCycleLimitEstimation() { 34 | 35 | int numberOfComponents = 10; 36 | SuperMinHashPolicy_v1b policy = 37 | new SuperMinHashPolicy_v1b( 38 | numberOfComponents, 3, PseudoRandomGeneratorProvider.splitMix64_V1()); 39 | assertThat(policy.estimateCycleLimit(1)).isEqualTo(10); 40 | assertThat(policy.estimateCycleLimit(2)).isEqualTo(10); 41 | assertThat(policy.estimateCycleLimit(3)).isEqualTo(9); 42 | assertThat(policy.estimateCycleLimit(4)).isEqualTo(9); 43 | assertThat(policy.estimateCycleLimit(5)).isEqualTo(8); 44 | assertThat(policy.estimateCycleLimit(1000)).isEqualTo(1); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/com/dynatrace/hash4j/similarity/SuperMinHashVersionTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.similarity; 17 | 18 | import static org.assertj.core.api.Assertions.assertThat; 19 | 20 | import org.junit.jupiter.api.Test; 21 | 22 | class SuperMinHashVersionTest { 23 | 24 | @Test 25 | void testConstants() { 26 | assertThat(SuperMinHashVersion.DEFAULT.create(3, 5)).isInstanceOf(SuperMinHashPolicy_v1.class); 27 | assertThat(SuperMinHashVersion.V1.create(3, 5)).isInstanceOf(SuperMinHashPolicy_v1.class); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java21/com/dynatrace/hash4j/internal/UnsignedMultiplyUtilReferenceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025 Dynatrace LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.dynatrace.hash4j.internal; 17 | 18 | import static org.assertj.core.api.AssertionsForClassTypes.assertThat; 19 | 20 | import java.util.SplittableRandom; 21 | import org.junit.jupiter.api.Test; 22 | 23 | public class UnsignedMultiplyUtilReferenceTest { 24 | 25 | @Test 26 | public void testAgainstJava() { 27 | 28 | SplittableRandom random = new SplittableRandom(0x75ec0a7f2d98ba4fL); 29 | int numIterations = 50; 30 | for (int i = 0; i < numIterations; ++i) { 31 | long a = random.nextLong(); 32 | long b = random.nextLong(); 33 | assertThat(UnsignedMultiplyUtil.unsignedMultiplyHigh(a, b)) 34 | .isEqualTo(Math.unsignedMultiplyHigh(a, b)); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/test/resources/junit-platform.properties: -------------------------------------------------------------------------------- 1 | junit.jupiter.execution.parallel.enabled = true 2 | junit.jupiter.execution.parallel.mode.default = concurrent -------------------------------------------------------------------------------- /test-results/hyperloglog-estimation-error-p03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/hyperloglog-estimation-error-p03.png -------------------------------------------------------------------------------- /test-results/hyperloglog-estimation-error-p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/hyperloglog-estimation-error-p04.png -------------------------------------------------------------------------------- /test-results/hyperloglog-estimation-error-p05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/hyperloglog-estimation-error-p05.png -------------------------------------------------------------------------------- /test-results/hyperloglog-estimation-error-p06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/hyperloglog-estimation-error-p06.png -------------------------------------------------------------------------------- /test-results/hyperloglog-estimation-error-p07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/hyperloglog-estimation-error-p07.png -------------------------------------------------------------------------------- /test-results/hyperloglog-estimation-error-p08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/hyperloglog-estimation-error-p08.png -------------------------------------------------------------------------------- /test-results/hyperloglog-estimation-error-p09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/hyperloglog-estimation-error-p09.png -------------------------------------------------------------------------------- /test-results/hyperloglog-estimation-error-p10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/hyperloglog-estimation-error-p10.png -------------------------------------------------------------------------------- /test-results/hyperloglog-estimation-error-p11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/hyperloglog-estimation-error-p11.png -------------------------------------------------------------------------------- /test-results/hyperloglog-estimation-error-p12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/hyperloglog-estimation-error-p12.png -------------------------------------------------------------------------------- /test-results/hyperloglog-estimation-error-p13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/hyperloglog-estimation-error-p13.png -------------------------------------------------------------------------------- /test-results/hyperloglog-estimation-error-p14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/hyperloglog-estimation-error-p14.png -------------------------------------------------------------------------------- /test-results/hyperloglog-estimation-error-p15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/hyperloglog-estimation-error-p15.png -------------------------------------------------------------------------------- /test-results/hyperloglog-estimation-error-p16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/hyperloglog-estimation-error-p16.png -------------------------------------------------------------------------------- /test-results/ultraloglog-estimation-error-p03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/ultraloglog-estimation-error-p03.png -------------------------------------------------------------------------------- /test-results/ultraloglog-estimation-error-p04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/ultraloglog-estimation-error-p04.png -------------------------------------------------------------------------------- /test-results/ultraloglog-estimation-error-p05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/ultraloglog-estimation-error-p05.png -------------------------------------------------------------------------------- /test-results/ultraloglog-estimation-error-p06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/ultraloglog-estimation-error-p06.png -------------------------------------------------------------------------------- /test-results/ultraloglog-estimation-error-p07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/ultraloglog-estimation-error-p07.png -------------------------------------------------------------------------------- /test-results/ultraloglog-estimation-error-p08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/ultraloglog-estimation-error-p08.png -------------------------------------------------------------------------------- /test-results/ultraloglog-estimation-error-p09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/ultraloglog-estimation-error-p09.png -------------------------------------------------------------------------------- /test-results/ultraloglog-estimation-error-p10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/ultraloglog-estimation-error-p10.png -------------------------------------------------------------------------------- /test-results/ultraloglog-estimation-error-p11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/ultraloglog-estimation-error-p11.png -------------------------------------------------------------------------------- /test-results/ultraloglog-estimation-error-p12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/ultraloglog-estimation-error-p12.png -------------------------------------------------------------------------------- /test-results/ultraloglog-estimation-error-p13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/ultraloglog-estimation-error-p13.png -------------------------------------------------------------------------------- /test-results/ultraloglog-estimation-error-p14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/ultraloglog-estimation-error-p14.png -------------------------------------------------------------------------------- /test-results/ultraloglog-estimation-error-p15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/ultraloglog-estimation-error-p15.png -------------------------------------------------------------------------------- /test-results/ultraloglog-estimation-error-p16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dynatrace-oss/hash4j/b16da7afce68fcd629a634975338c65f893db34e/test-results/ultraloglog-estimation-error-p16.png --------------------------------------------------------------------------------