Created
October 16, 2019 01:03
-
-
Save scoroberts/a60d61a2cc3afba1e8813b338ecd1501 to your computer and use it in GitHub Desktop.
Test of different Java based SHA-256 hash implementations
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Grab(group='com.google.guava', module='guava', version='19.0') | |
@Grab(group='commons-codec', module='commons-codec', version='1.13') | |
@Grab(group='bouncycastle', module='bcprov-jdk15', version='140') | |
import groovy.transform.CompileStatic | |
import java.security.MessageDigest | |
import java.nio.charset.StandardCharsets | |
import com.google.common.hash.Hashing | |
import org.apache.commons.codec.digest.DigestUtils | |
import org.bouncycastle.crypto.digests.SHA256Digest | |
//test string for all hashing implementations | |
String test = "lwkjt23uy45pojsdf;lnwo45y23po5i;lknwe;lknasdflnqw3uo5" | |
String hashJava(String str){ | |
MessageDigest digest = MessageDigest.getInstance("SHA-256"); | |
byte[] encodedhash = digest.digest(str.getBytes(StandardCharsets.UTF_8)); | |
return bytesToHex(encodedhash) | |
} | |
@CompileStatic | |
String bytesToHex(byte[] hash) { | |
StringBuffer hexString = new StringBuffer(); | |
for (int i = 0; i < hash.length; i++) { | |
String hex = Integer.toHexString(0xff & hash[i]); | |
if(hex.length() == 1) hexString.append('0'); | |
hexString.append(hex); | |
} | |
return hexString.toString(); | |
} | |
@CompileStatic | |
String groovyHash(String str){ | |
str.digest('SHA-256') | |
} | |
@CompileStatic | |
String guavaHash(String str){ | |
Hashing.sha256().hashString(str, StandardCharsets.UTF_8).toString(); | |
} | |
@CompileStatic | |
String apacheHash(String str){ | |
DigestUtils.sha256Hex(str) | |
} | |
@CompileStatic | |
String bouncyHash(String str){ | |
SHA256Digest digest = new SHA256Digest(); | |
byte[] keyByteArray = str.getBytes(StandardCharsets.UTF_8) | |
byte[] output = new byte[digest.getDigestSize()]; | |
digest.update(keyByteArray, 0, keyByteArray.length); | |
digest.doFinal(output, 0); | |
bytesToHex(output) | |
} | |
long iterations = 100_0000 | |
println "Hashing ${iterations} iterations of SHA-256" | |
//warm up, throw away | |
for (int x=0; x<1000; x++) hashJava(test) | |
long start = System.currentTimeMillis() | |
for (int x=0; x<iterations; x++) hashJava(test) | |
long end = System.currentTimeMillis() | |
println ("time java: ${end-start}\t\t${iterations*1000/(end-start)} hashes/sec") | |
for (int x=0; x<1000; x++) groovyHash(test) | |
start = System.currentTimeMillis() | |
for (int x=0; x<iterations; x++) groovyHash(test) | |
end = System.currentTimeMillis() | |
println ("time groovy: ${end-start}\t${iterations*1000/(end-start)} hashes/sec") | |
for (int x=0; x<1000; x++) apacheHash(test) | |
start = System.currentTimeMillis() | |
for (int x=0; x<iterations; x++) apacheHash(test) | |
end = System.currentTimeMillis() | |
println ("time apache: ${end-start}\t\t${iterations*1000/(end-start)} hashes/sec") | |
for (int x=0; x<1000; x++) guavaHash(test) | |
start = System.currentTimeMillis() | |
for (int x=0; x<iterations; x++) guavaHash(test) | |
end = System.currentTimeMillis() | |
println ("time guava: ${end-start}\t\t${iterations*1000/(end-start)} hashes/sec") | |
for (int x=0; x<1000; x++) bouncyHash(test) | |
start = System.currentTimeMillis() | |
for (int x=0; x<iterations; x++) bouncyHash(test) | |
end = System.currentTimeMillis() | |
println ("time bouncy: ${end-start}\t\t${iterations*1000/(end-start)} hashes/sec") |
I did, same performance difference even in different order with different
warms ups. Something different is happening even if same algo
implementation.
On Wed, Nov 6, 2019 at 9:54 AM Marcel Hellkamp ***@***.***> wrote:
Apache commons-codec does not implement its own MessageDigest algorithms,
but uses the standard java implementation. Apache beeing more than twice as
fast as java would not make any sense. Whatever your benchmark is
measuring, it is not SHA256 performance.
Your warm-up phase is probably way too short. Switching around the order
in which the tests are run will significantly change the results.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<https://gist.github.com/a60d61a2cc3afba1e8813b338ecd1501?email_source=notifications&email_token=AAA6NSC5GRN6AIB6JXZJ6YLQSMAETA5CNFSM4JBEZVS2YY3PNVWWK3TUL52HS4DFVNDWS43UINXW23LFNZ2KUY3PNVWWK3TUL5UWJTQAF3XVO#gistcomment-3075927>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAA6NSEBED3UZUEREQIQB7LQSMAETANCNFSM4JBEZVSQ>
.
--
Sent from my phone
Took advice to remove the String conversion portions here: https://gist.github.com/scoroberts/77cc2d5c28fa2faeb1626d8eb39ec8c8
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I think
bytesToHex
function makes the performance for MessageDigest and commons-codec different. If make bothhashJava
andapacheHash
returnbyte[]
to avoid transforming to hex string. Then they can get similar results.