3

ハッシュアルゴリズムについてはよくわかりません。

MD2/MD5/SHA-X でファイル ハッシュを必要とするリモート システム (S3 に少し似ています) にファイルを転送する前に、Java でライブの着信ファイルのハッシュを計算する必要があります。このハッシュは、セキュリティ上の理由からではなく、単に一貫性チェックサムのために計算されます。

Java 標準ライブラリの DigestInputStream を使用して、ファイルの転送中にこのハッシュをライブで計算できますが、DigestInputStream を使用する際のパフォーマンスの問題を回避するためにどのアルゴリズムを使用するのが最適かを知りたいですか?

私の元同僚の 1 人がテストを行い、ライブでハッシュを計算すると、UNIX のコマンド ラインやファイルに比べて非常にコストがかかる可能性があると教えてくれました。


時期尚早の最適化に関する編集: 私は、他の企業が文書を非物質化するのを支援することを目的とした会社で働いています。これは、他社からのドキュメント転送を処理するバッチがあることを意味します。将来的には、1 日あたり数百万のドキュメントを目標にしていますが、実際には、このバッチの実行時間はビジネスにとって重要です。

1 日あたり 100 万件のドキュメントに対して 10 ミリ秒のハッシュ最適化は、1 日あたりの実行時間を 3 時間短縮します。

4

3 に答える 3

5

送信中などの偶発的な破損を単に検出したい場合は、単純な (暗号化されていない) チェックサムで十分です。ただし、(たとえば) 16 ビットのチェックサムでは、2 16に 1 回、ランダムな破損の検出に失敗することに注意してください。また、誰かが故意にデータを変更することに対しては無防備です。

Checksumsに関するウィキペディアのページには、Adler-32 や CRC などの一般的に使用される (そして安価な) オプションを含むさまざまなオプションがリストされています。

ただし、@ppeterka に同意します。これは「時期尚早の最適化」のにおいがします。

于 2013-10-03T11:10:47.150 に答える
1

NKukhar のように、マイクロ ベンチマークを実行しようとしましたが、別のコードとより良い結果が得られました。

public static void main(String[] args) throws Exception {
    String bigFile = "100mbfile";


    // We put the file bytes in memory, we don't want to mesure the time it takes to read from the disk
    byte[] bigArray = IOUtils.toByteArray(Files.newInputStream(Paths.get(bigFile)));
    byte[] buffer = new byte[50_000]; // the byte buffer we will use to consume the stream

    // we prepare the algos to test
    Set<String> algos = ImmutableSet.of(
            "no_hash", // no hashing
            MessageDigestAlgorithms.MD5,
            MessageDigestAlgorithms.SHA_1,
            MessageDigestAlgorithms.SHA_256,
            MessageDigestAlgorithms.SHA_384,
            MessageDigestAlgorithms.SHA_512
    );

    int executionNumber = 20;

    for ( String algo : algos ) {
      long totalExecutionDuration = 0;
      for ( int i = 0 ; i < 20 ; i++ ) {
        long beforeTime = System.currentTimeMillis();
        InputStream is = new ByteArrayInputStream(bigArray);
        if ( !"no_hash".equals(algo) ) {
          is = new DigestInputStream(is, MessageDigest.getInstance(algo));
        }
        while ((is.read(buffer)) != -1) {  }
        long executionDuration = System.currentTimeMillis() - beforeTime;
        totalExecutionDuration += executionDuration;
      }
      System.out.println(algo + " -> average of " + totalExecutionDuration/executionNumber + " millies per execution");
    }
  }

これにより、適切な i7 開発者マシンで 100 MB ファイルの次の出力が生成されます。

no_hash -> average of 6 millies per execution
MD5 -> average of 201 millies per execution
SHA-1 -> average of 335 millies per execution
SHA-256 -> average of 576 millies per execution
SHA-384 -> average of 481 millies per execution
SHA-512 -> average of 464 millies per execution
于 2013-10-03T13:28:31.080 に答える