Computing cryptography hashes: Rust, F#, D and Scala

Let's compare how fast Rust, D and F# (.NET actually) at computing cryptography hashes, namely MD5, SHA1, SHA256 and SHA512. We're going to use rust-crypto cargo:

Results:
  • MD5 - 3.39s 
  • SHA1 - 2.89s 
  • SHA256 - 6.97s
  • SHA512 - 4.47s

Now the F# code:


Results (.NET 4.5, VS 2013, F# 3.1):
  • MD5CryptoServiceProvider - 2.32s (32% faster)
  • SHA1CryptoServiceProvider - 2.92s (1% slower)
  • SHA256Managed - 16.50s (236% slower)
  • SHA256CryptoServiceProvider - 11.50s (164% slower)
  • SHA256Cng - 11.71s (168% slower)
  • SHA512Managed - 61.04s (1365% slower)
  • SHA512CryptoServiceProvider - 21.88s (489% slower)
  • SHA512Cng - 22.19s (496% slower)
(.NET 4.6, VS 2015, F# 4.0):

  • MD5CryptoServiceProvider elapled 2.55
  • SHA1CryptoServiceProvider elapled 2.89
  • SHA256Managed elapled 17.01
  • SHA256CryptoServiceProvider elapled 8.74
  • SHA256Cng elapled 8.75
  • SHA512Managed elapled 23.42
  • SHA512CryptoServiceProvider 5.81
  • SHA512Cng elapled 5.79



D:



DMD
  • MD5 - 16.05s (470% slower)
  • SHA1 - 2.35s (19% faster)
  • SHA256 - 47.96s (690% slower (!))
  • SHA512 - 61.47s (1375% slower (!))
LDC2
  • MD5 - 2,18s (55% faster)
  • SHA1 - 2.88s (same)
  • SHA256 - 6,79s (3% faster)
  • SHA512 - 4,6s (3% slower)
GDC
  • MD5 - 2,43 (29% faster)
  • SHA1 - 2,84 (2% faster)
  • SHA256 - 12,62 (45% slower)
  • SHA512 - 8,56 (48% slower)


Scala:



  • MD5 - 4.2s (23% slower)
  • SHA1 - 6.09s (110% slower)
  • SHA256 - 9.96s (42% slower)
  • SHA512 - 7.32s (63% slower)
Interesting things:

  • Rust and D (LDC2) show very close results. D is significantly faster on MD5, so it's the winner!
  • D (DMD) has very bad performance on all algorithms, except SHA1, where it's won.
  • SHA512Managed .NET class is very slow. Do not use it.



Comments

Unknown said…
You can speed up the hash generation in F# for SHA:

bench (new SHA256CryptoServiceProvider()) input
bench (new SHA512CryptoServiceProvider()) input

It probably works only on Windows, but it gives a huge performance improvement (nearly on par with rust).
Vasily said…
Thanks! I added more .NET algorithms and a chart.
Unknown said…
JFYI. dmd, D's official compiler, is not good for numerical computing.
So some D users use gdc(gcc)/ldc(llvm) for such cases, e.g. cryptography, machine learning, statistics and etc.

I tested your code and dmd / ldc results on my MBP are below:

dmd 2.067:

MD5 - 8363 ms elapsed.
SHA1 - 16611 ms elapsed.
SHA256 - 35451 ms elapsed.
SHA512 - 24743 ms elapsed.

ldc2-0.15.2-beta1:

MD5 - 1970 ms elapsed.
SHA1 - 1676 ms elapsed.
SHA256 - 4273 ms elapsed.
SHA512 - 2964 ms elapsed.

ldc's performance is quite similar to Rust :)
Vasily said…
@Mr. Fiber: Thanks, it's very interesting. I've not touch LDC compiler yet. It's also interesting how dramatically your DMD results are differ from mine (expecially for SHA-1).
Anonymous said…
Hi,
using LDC for D I had D come out faster in all four.
Could you please retry with LDC? dmd is just a reference implementation(ala cpython) with a very old, poorly optimizing backend based on Zortech/Digital Mars C++.

Suggested flags:
ldc -O5 -release

Bye,
Vasily said…
I tried to compile with LDC2 and failed (windows 7 x64):

d:\ldc2-0.15.2-beta1-win64-msvc\bin\ldc2.exe -O5 -release main.d
OPTLINK (R) for Win32 Release 8.00.17
Copyright (C) Digital Mars 1989-2013 All rights reserved.
http://www.digitalmars.com/ctg/optlink.html
OPTLINK : Warning 9: Unknown Option : NXCOMPAT
OPTLINK : Warning 9: Unknown Option : DYNAMICBASE
OPTLINK : Warning 9: Unknown Option : OUT
OPTLINK : Error 8: Illegal Filename
/NOLOGO /NXCOMPAT /DYNAMICBASE /LARGEADDRESSAWARE /OPT:REF /OPT:ICF /OUT:main.exe main.obj "/LIBPATH
:d:\ldc2-0.15.2-beta1-win64-msvc\bin/../lib" phobos2-ldc.lib druntime-ldc.lib kernel32.lib user32.li
b gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib

^
Error: d:\DMD\dmd2\windows\bin\link.exe failed with status: 1

__________________________


What am I doing wrong?
Anonymous said…
@Vasily: LDC-win64-msvc uses Visual C++ linker (link.exe) but error message says that DMD's link.exe was invoked. Make sure that VC++ linker in your PATH when you run ldc2.
Vasily said…
Thanks! Fixed it. Updated the post with LDC2 results. It's not faster than Rust, but close.
Anonymous said…
"D has very bad performance on all algorithms, except SHA1, where it's won."

Looks like after the LDC inclusion, D wins 3 out of 4 times.
Vasily said…
Updated the summary :)
plinth said…
Scala is using the JVM implementation, which may or may not be in native code.
It would be interesting to see Bouncy Castle for both .NET and JVM implementations.
ark trike egg said…
Thanks for the comment! Cryptographic hash functions are used in both transaction records and transaction block chains. So, think of this video as a precursor to those videos, which go into more detail. The first video in the series ("Bitcoin - overview") is meant to lay out all the pieces, with the subsequent videos going into the details of the underlying mechanics of bitcoins. 
Read more

The download verification hash is usually to verify that the download was received without being corrupted during transmission, not really for security.
Cryptographic hash functions are used in both transaction records and transaction block chains. So, think of this video as a precursor to those videos, which go into more detail. The first video in the series ("Bitcoin - overview") is meant to lay out all the pieces, with the subsequent videos going into the details of the underlying mechanics of bitcoins. 

Popular posts from this blog

Haskell: performance

Regular expressions: Rust vs F# vs Scala

Hash maps: Rust, F#, D, Go, Scala