17dd252788645e940eada959bdde927426e2531c9Paul Duffin/* 27dd252788645e940eada959bdde927426e2531c9Paul Duffin * Copyright (C) 2012 The Guava Authors 37dd252788645e940eada959bdde927426e2531c9Paul Duffin * 47dd252788645e940eada959bdde927426e2531c9Paul Duffin * Licensed under the Apache License, Version 2.0 (the "License"); 57dd252788645e940eada959bdde927426e2531c9Paul Duffin * you may not use this file except in compliance with the License. 67dd252788645e940eada959bdde927426e2531c9Paul Duffin * You may obtain a copy of the License at 77dd252788645e940eada959bdde927426e2531c9Paul Duffin * 87dd252788645e940eada959bdde927426e2531c9Paul Duffin * http://www.apache.org/licenses/LICENSE-2.0 97dd252788645e940eada959bdde927426e2531c9Paul Duffin * 107dd252788645e940eada959bdde927426e2531c9Paul Duffin * Unless required by applicable law or agreed to in writing, software 117dd252788645e940eada959bdde927426e2531c9Paul Duffin * distributed under the License is distributed on an "AS IS" BASIS, 127dd252788645e940eada959bdde927426e2531c9Paul Duffin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137dd252788645e940eada959bdde927426e2531c9Paul Duffin * See the License for the specific language governing permissions and 147dd252788645e940eada959bdde927426e2531c9Paul Duffin * limitations under the License. 157dd252788645e940eada959bdde927426e2531c9Paul Duffin */ 167dd252788645e940eada959bdde927426e2531c9Paul Duffin 177dd252788645e940eada959bdde927426e2531c9Paul Duffinpackage com.google.common.hash; 187dd252788645e940eada959bdde927426e2531c9Paul Duffin 190888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport com.google.caliper.BeforeExperiment; 200888a09821a98ac0680fad765217302858e70fa4Paul Duffinimport com.google.caliper.Benchmark; 217dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.caliper.Param; 227dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.hash.HashFunction; 237dd252788645e940eada959bdde927426e2531c9Paul Duffinimport com.google.common.hash.Hashing; 247dd252788645e940eada959bdde927426e2531c9Paul Duffin 257dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.security.MessageDigest; 267dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.security.NoSuchAlgorithmException; 277dd252788645e940eada959bdde927426e2531c9Paul Duffinimport java.util.Random; 287dd252788645e940eada959bdde927426e2531c9Paul Duffin 297dd252788645e940eada959bdde927426e2531c9Paul Duffin/** 307dd252788645e940eada959bdde927426e2531c9Paul Duffin * Benchmarks for comparing {@link MessageDigest}s and {@link HashFunction}s that wrap 317dd252788645e940eada959bdde927426e2531c9Paul Duffin * {@link MessageDigest}s. 327dd252788645e940eada959bdde927426e2531c9Paul Duffin * 337dd252788645e940eada959bdde927426e2531c9Paul Duffin * <p>Parameters for the benchmark are: 347dd252788645e940eada959bdde927426e2531c9Paul Duffin * <ul> 357dd252788645e940eada959bdde927426e2531c9Paul Duffin * <li>size: The length of the byte array to hash. 367dd252788645e940eada959bdde927426e2531c9Paul Duffin * <li>algorithm: the algorithm to hash with (e.g. MD5, SHA1, etc.). 377dd252788645e940eada959bdde927426e2531c9Paul Duffin * <li>hashMethod: how to hash the data (using the Hashing API or the MessageDigest API). 387dd252788645e940eada959bdde927426e2531c9Paul Duffin * </ul> 397dd252788645e940eada959bdde927426e2531c9Paul Duffin * 407dd252788645e940eada959bdde927426e2531c9Paul Duffin * @author Kurt Alfred Kluever 417dd252788645e940eada959bdde927426e2531c9Paul Duffin */ 420888a09821a98ac0680fad765217302858e70fa4Paul Duffinpublic class MessageDigestAlgorithmBenchmark { 437dd252788645e940eada959bdde927426e2531c9Paul Duffin @Param({"10", "1000", "100000", "1000000"}) int size; 447dd252788645e940eada959bdde927426e2531c9Paul Duffin @Param Algorithm algorithm; 457dd252788645e940eada959bdde927426e2531c9Paul Duffin @Param HashMethod hashMethod; 467dd252788645e940eada959bdde927426e2531c9Paul Duffin 477dd252788645e940eada959bdde927426e2531c9Paul Duffin private enum HashMethod { 487dd252788645e940eada959bdde927426e2531c9Paul Duffin MESSAGE_DIGEST_API() { 497dd252788645e940eada959bdde927426e2531c9Paul Duffin @Override public byte[] hash(Algorithm algorithm, byte[] input) { 507dd252788645e940eada959bdde927426e2531c9Paul Duffin MessageDigest md = algorithm.getMessageDigest(); 517dd252788645e940eada959bdde927426e2531c9Paul Duffin md.update(input); 527dd252788645e940eada959bdde927426e2531c9Paul Duffin return md.digest(); 537dd252788645e940eada959bdde927426e2531c9Paul Duffin } 547dd252788645e940eada959bdde927426e2531c9Paul Duffin }, 557dd252788645e940eada959bdde927426e2531c9Paul Duffin HASH_FUNCTION_API() { 567dd252788645e940eada959bdde927426e2531c9Paul Duffin @Override public byte[] hash(Algorithm algorithm, byte[] input) { 577dd252788645e940eada959bdde927426e2531c9Paul Duffin return algorithm.getHashFunction().hashBytes(input).asBytes(); 587dd252788645e940eada959bdde927426e2531c9Paul Duffin } 597dd252788645e940eada959bdde927426e2531c9Paul Duffin }; 607dd252788645e940eada959bdde927426e2531c9Paul Duffin public abstract byte[] hash(Algorithm algorithm, byte[] input); 617dd252788645e940eada959bdde927426e2531c9Paul Duffin } 627dd252788645e940eada959bdde927426e2531c9Paul Duffin 637dd252788645e940eada959bdde927426e2531c9Paul Duffin private enum Algorithm { 647dd252788645e940eada959bdde927426e2531c9Paul Duffin MD5("MD5", Hashing.md5()), 657dd252788645e940eada959bdde927426e2531c9Paul Duffin SHA_1("SHA-1", Hashing.sha1()), 667dd252788645e940eada959bdde927426e2531c9Paul Duffin SHA_256("SHA-256", Hashing.sha256()), 677dd252788645e940eada959bdde927426e2531c9Paul Duffin SHA_512("SHA-512", Hashing.sha512()); 687dd252788645e940eada959bdde927426e2531c9Paul Duffin 697dd252788645e940eada959bdde927426e2531c9Paul Duffin private final String algorithmName; 707dd252788645e940eada959bdde927426e2531c9Paul Duffin private final HashFunction hashFn; 717dd252788645e940eada959bdde927426e2531c9Paul Duffin Algorithm(String algorithmName, HashFunction hashFn) { 727dd252788645e940eada959bdde927426e2531c9Paul Duffin this.algorithmName = algorithmName; 737dd252788645e940eada959bdde927426e2531c9Paul Duffin this.hashFn = hashFn; 747dd252788645e940eada959bdde927426e2531c9Paul Duffin } 757dd252788645e940eada959bdde927426e2531c9Paul Duffin public MessageDigest getMessageDigest() { 767dd252788645e940eada959bdde927426e2531c9Paul Duffin try { 777dd252788645e940eada959bdde927426e2531c9Paul Duffin return MessageDigest.getInstance(algorithmName); 787dd252788645e940eada959bdde927426e2531c9Paul Duffin } catch (NoSuchAlgorithmException e) { 797dd252788645e940eada959bdde927426e2531c9Paul Duffin throw new AssertionError(e); 807dd252788645e940eada959bdde927426e2531c9Paul Duffin } 817dd252788645e940eada959bdde927426e2531c9Paul Duffin } 827dd252788645e940eada959bdde927426e2531c9Paul Duffin public HashFunction getHashFunction() { 837dd252788645e940eada959bdde927426e2531c9Paul Duffin return hashFn; 847dd252788645e940eada959bdde927426e2531c9Paul Duffin } 857dd252788645e940eada959bdde927426e2531c9Paul Duffin } 867dd252788645e940eada959bdde927426e2531c9Paul Duffin 877dd252788645e940eada959bdde927426e2531c9Paul Duffin // Use a constant seed for all of the benchmarks to ensure apples to apples comparisons. 887dd252788645e940eada959bdde927426e2531c9Paul Duffin private static final int RANDOM_SEED = new Random().nextInt(); 897dd252788645e940eada959bdde927426e2531c9Paul Duffin 907dd252788645e940eada959bdde927426e2531c9Paul Duffin private byte[] testBytes; 917dd252788645e940eada959bdde927426e2531c9Paul Duffin 920888a09821a98ac0680fad765217302858e70fa4Paul Duffin @BeforeExperiment void setUp() { 937dd252788645e940eada959bdde927426e2531c9Paul Duffin testBytes = new byte[size]; 947dd252788645e940eada959bdde927426e2531c9Paul Duffin new Random(RANDOM_SEED).nextBytes(testBytes); 957dd252788645e940eada959bdde927426e2531c9Paul Duffin } 967dd252788645e940eada959bdde927426e2531c9Paul Duffin 970888a09821a98ac0680fad765217302858e70fa4Paul Duffin @Benchmark byte hashing(int reps) { 987dd252788645e940eada959bdde927426e2531c9Paul Duffin byte result = 0x01; 997dd252788645e940eada959bdde927426e2531c9Paul Duffin HashMethod hashMethod = this.hashMethod; 1007dd252788645e940eada959bdde927426e2531c9Paul Duffin Algorithm algorithm = this.algorithm; 1017dd252788645e940eada959bdde927426e2531c9Paul Duffin for (int i = 0; i < reps; i++) { 1027dd252788645e940eada959bdde927426e2531c9Paul Duffin result ^= hashMethod.hash(algorithm, testBytes)[0]; 1037dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1047dd252788645e940eada959bdde927426e2531c9Paul Duffin return result; 1057dd252788645e940eada959bdde927426e2531c9Paul Duffin } 1067dd252788645e940eada959bdde927426e2531c9Paul Duffin} 107