Javaでbyte配列を16進文字列にする時の速度比較
Javaでプログラミングしていると、byte配列(byte[])を16進の文字列に変換したいことは多い。
例えば、MD5やSHA-1,SHA-512などハッシュ値に置き換えるときや、バイナリデータのバンプなどがある。
上記のコードは、様々なところで紹介されているが、いったいどの方法が速いのだろうか?
VM環境は、Windows 7 + Oracle JRE 7 という、とても一般的な環境。
試したパターンは、10通り。そのうち比較として面白いものを4つ選んだ。
どのパターンも前提として、by:byte[]、sb:StringBuilder、とする。
パターン1は、フォーマット文字列の解析があるので、明らかに遅くなるのは間違いない。ほぼ予想通りであるといえる。
パターン2とパターン3からいえることは、これらの処理の中でInteger.toHexString()が一番時間がかかるといえる。
結果としては、パターン4が明らかに速い。理由はOpenJDKのソースを見ると明らかだ。
Integer.toHexStringは複数の桁を検査し、それをnew String()している。
Character.forDigitは1桁目のみ検査し、それをcharで返している。
charはintと同様クラスではないので速いのだろう。Stringはクラスなので、生成にコストがかかる。
今回の調査でわかったことは、Stringの生成は意外とコストが大きく、StringBuilder.append()は速いということだった。
Stringの生成が遅いので作られたものがStringBuilderという点からしても当たり前か。
例えば、MD5やSHA-1,SHA-512などハッシュ値に置き換えるときや、バイナリデータのバンプなどがある。
上記のコードは、様々なところで紹介されているが、いったいどの方法が速いのだろうか?
VM環境は、Windows 7 + Oracle JRE 7 という、とても一般的な環境。
試したパターンは、10通り。そのうち比較として面白いものを4つ選んだ。
どのパターンも前提として、by:byte[]、sb:StringBuilder、とする。
//パターン1 for (byte b : by) sb.append(String.format("%02x", b));
//パターン2 for (int b : by) { sb.append(Integer.toHexString(b >> 4 & 0xF)); sb.append(Integer.toHexString(b & 0xF)); }
//パターン3 for (int b : by) { int b2 = b & 0xff; if (b2 < 16) sb.append("0"); sb.append(Integer.toHexString(b2)); }
//パターン4 for (int b : by) { sb.append(Character.forDigit(b >> 4 & 0xF, 16)); sb.append(Character.forDigit(b & 0xF, 16)); }実行結果は、以下のとおりである。
パターン | 実行時間 |
---|---|
パターン1 | 47817ms |
パターン2 | 4313ms |
パターン3 | 2310ms |
パターン4 | 588ms |
コメント
コメントを投稿