【问题标题】:Hashing speed - cryptic results (Hashing twice much slower than hashing once)哈希速度 - 神秘的结果(哈希两次比一次哈希慢得多)
【发布时间】:2015-08-31 09:30:07
【问题描述】:

我试图理解为什么多个散列的散列比一个散列慢。在下面的测试中,我对一个文件进行了两次哈希处理——首先使用 SHA1,然后使用 SHA1 和 SHA256。第一次执行显示了预期的结果 - 磁盘读取占主导地位 - 两者都花费了大约 30 秒(尽管有更多的工作,但后者大约少了一秒)。

但是,在随后的执行中,我得到了一个奇怪的结果:第一次执行大约 10 秒,第二次执行大约 30 秒。 10 表示原始磁盘读取需要 20 秒,30 表示几乎没有时间。这可能真的意味着由于某种原因,散列一次比两次快得多。但为什么呢?

这里发生了什么?

代码:

Text = TestSpeed(new HashAlgorithm[] { new SHA1Managed() }, path);
Text += " " + TestSpeed(new HashAlgorithm[] { new SHA1Managed(), new SHA256Managed() }, path);

还有:

public string TestSpeed(HashAlgorithm[] algorithms, string path)
{
    Stopwatch sw = new Stopwatch();
    sw.Start();

    byte[] block = new byte[65536];
    int bytesRead = 0;
    using (FileStream stream = new FileStream(path, FileMode.Open))
        while ((bytesRead = stream.Read(block, 0, block.Length)) > 0)
            foreach (HashAlgorithm algorithm in algorithms)
                algorithm.TransformBlock(block, 0, bytesRead, null, 0);
    foreach (HashAlgorithm algorithm in algorithms)
        algorithm.TransformFinalBlock(block, 0, 0);

    sw.Stop();
    return sw.Elapsed.ToString();
}

【问题讨论】:

  • 你正在重塑HashAlgorithm.ComputeHashreferencesource.microsoft.com/#mscorlib/system/security/…
  • 听起来像缓存,而不是散列......第一次迭代有磁盘 i/o 增加了测试 1 的运行时间,因为测试 2 磁盘读取被缓存。在随后的迭代中,所有读取都被缓存,返回预期的结果。确实,如果此代码很重要,您应该对其进行分析 - 这将清楚地揭示您的执行时间花费在哪里以及它在后续迭代中如何变化。
  • 事情太多了。处理器缓存未命中、计算机上的其他任务干扰、磁盘文件碎片等。良好的分析是hard
  • @SLaks 此代码是由我的原始代码编写的,需要逐步散列。
  • @Jay 如果差异很小,或者后续执行不一致 - 我同意。

标签: c# .net hash


【解决方案1】:

您的结果很可能是由磁盘缓存引起的。假设两个测试都对相同的数据进行操作,那么只有第一次读取会导致大量的 I/O 时间。即:

  • 迭代 1,测试 1:30 秒(= 20 秒磁盘读取,10 秒工作)。
  • 迭代 1,测试 2:30 秒(= 0 秒磁盘读取,30 秒工作)。
  • 迭代 2,测试 1:10 秒(= 0 秒磁盘读取,10 秒工作)。
  • 迭代 2,测试 2:30 秒(= 0 秒磁盘读取,30 秒工作)。
  • ...等。

这意味着哈希两次所需的时间大约是哈希一次的三倍。由于 SHA256 的性能通常是 SHA1 的一半左右,因此这似乎是一个合理的结果。

您可以通过在开始测试之前先将文件读入内存流并在测试期间将内存流用于所有读取来解除这种影响。分析会向您显示您的执行时间花费在哪里。

【讨论】:

  • 谢谢!我不知道我是怎么错过的。
  • 顺便说一句,这意味着对文件进行 SHA256 处理的时间与从驱动器读取文件所需的时间一样长(尽管 USB 连接速度较慢)。对我来说 - 这很令人惊讶。
  • @ispiro 这取决于驱动器、USB 连接的质量、算法实现的性能以及计算机的速度。一个相当快的 USB3.0 驱动器可以为连续文件提供高持续读取 (~80-100MB/s)。中级计算机可以以大致相同的速率(再次,~100MB/s 左右)进行 SHA256。没有剖析真的很难说...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-27
  • 2015-10-06
  • 2012-08-17
  • 1970-01-01
  • 2017-04-24
  • 2013-09-12
相关资源
最近更新 更多