Vasily's blog: Computing cryptography hashes: Rust, F#, D and Scala
この記事見て,D言語のハッシュ実装ってそんなに変な実装だったかな?とソースを見たけど特別遅そうな実装には見えない.で,よくよく考えたらdmdってこの手のヘビーな計算関係の最適化弱かったなぁと思い出したので,LLVMをバックエンドにしているldcで試したらRustとほぼ同じ速度だった(少し速い)ので安心した,という単なるメモ記事.
Rust
Duration
の出力が見えにくかったので,msに変更.Rust 1.0.0とrust-cryptoは0.2.31を使った.
extern crate crypto;
extern crate time;
use crypto::md5::Md5;
use crypto::sha1::Sha1;
use crypto::sha2::{Sha256, Sha512};
use crypto::digest::Digest;
use time::now;
fn bench<T: Digest>(name: &str, digest: &mut T, input: &Vec<u8>) {
let started = time::now();
for _ in 1..100 {
digest.input(&input);
digest.reset();
}
let elapsed = time::now() - started;
println!("{:?} elapled {:?}", name, elapsed.num_milliseconds());
}
fn main() {
let input = vec![0u8; 10000000];
bench("MD5", &mut Md5::new(), &input);
bench("SHA1", &mut Sha1::new(), &input);
bench("SHA256", &mut Sha256::new(), &input);
bench("SHA512", &mut Sha512::new(), &input);
}
結果:
"MD5" elapled 1977
"SHA1" elapled 1812
"SHA256" elapled 4524
"SHA512" elapled 2678
D言語
Rustの実装に合わせて,finish
じゃなくてRustのreset
相当のstart
にした.
module main;
import std.stdio;
import std.digest.md;
import std.digest.sha;
import std.datetime;
void bench(T)(string name, T digest, const ubyte[] input) {
auto sw = StopWatch(AutoStart.yes);
for (auto i = 0; i < 100; i++) {
digest.put(input);
digest.start();
//auto hash = digest.finish();
}
sw.stop();
writefln("%s - %s ms elapsed.", name, sw.peek.msecs);
}
void main(string[] args)
{
auto input = new const ubyte[10_000_000];
MD5 md5; bench("MD5", md5, input);
SHA1 sha1; bench("SHA1", sha1, input);
SHA256 sha256; bench("SHA256", sha256, input);
SHA512 sha512; bench("SHA512", sha512, input);
}
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.
多分gdcでもldcに近いパフォーマンス出るはず.数値計算とかにD言語使っている人達がgdc/ldcを使いまくっているの,これは仕方ないなという感じですね…