【问题标题】:Best way to compare sha1 hashes for equality比较 sha1 哈希是否相等的最佳方法
【发布时间】:2012-03-14 08:31:22
【问题描述】:

我想比较两个 sha1 哈希值是否相等。最有效的方法是什么?目前,我正在尝试使用 memcmp。谢谢。

【问题讨论】:

  • 真正的问题应该是:何必呢?您真的需要比您当前的解决方案更快的东西吗?我怀疑比较 SHA1 是您应用程序的瓶颈。
  • @FerdinandBeyer 好点
  • 我完全同意费迪南德的观点,您正在尝试做的事情被称为“过早的优化”,应该避免......
  • 嗯.. @FredOverflow 解决方案 (is_same_sha1) 似乎比 memcmp 更快,而且不可忽略。谢谢你。我只是想看看我是否可以让它更快。它有什么问题?
  • @FredOverflow 我测量了整个程序的性能,结果证明它比 memcmp 快。

标签: c++ hash equality memcmp


【解决方案1】:

好吧,既然您在编译时已经知道块有多大,那么您可以这样做:

#include <cstdint>

bool is_same_sha1(const char* p, const char* q)
{
    const std::uint32_t* a = (const std::uint32_t*)p;
    const std::uint32_t* b = (const std::uint32_t*)q;
    return a[0] == b[0] && a[1] == b[1] && a[2] == b[2]
        && a[3] == b[3] && a[4] == b[4];
}

但不要盲目接受我的建议,您应该针对memcmp 解决方案衡量任何自定义解决方案,并且只有在它为您带来显着的性能优势时才使用它。如果memcmp 仍然更快,我什至不会感到惊讶,因为它做了一些非常聪明和肮脏的事情。

【讨论】:

  • 这似乎是一个很好的解决方案。对于我来说,它比 memcmp 快。谢谢。虽然我必须看看 std::equal 是否有什么不同。
  • 如果缓冲区没有正确对齐,这可能会失败。 (这也是形式上未定义的行为,但很明显,其意图是如果满足诸如对齐之类的外部约束,如果没有满足,这将是一个非常糟糕的实现。)
  • 当然,uint32_t 可能不可用。 (最后,这取决于您的可移植性限制。uint32_t 在 Windows 和 Posix 兼容系统下可用。并且有很多应用程序足够便携。)
  • @JamesKanze 你能详细说明一下吗?缓冲区对齐在哪里出现?
  • @polapts:在 C 和 C++ 中,类型可能有对齐要求,这意味着指向该类型的指针的地址必须被所需的对齐方式整除。 uint32_t 的对齐要求通常为 4。所以,如果pq 碰巧不是4 对齐的,那么将它们转换为uint32_t* 是未定义的行为。例如,如果我写 const char *foo == "11..1",其中有 21 位数字,那么 is_same_sha1(foo, foo+1) 是 UB 在需要对 uint32_t 进行 4 对齐的实现上,因为 foofoo+1 不能都是 4 对齐.
【解决方案2】:

memcmp() 有什么问题?您必须比较两个哈希的每个字节; memcmp() 将很快在它发现的第一个差异上失败;和 memcmp() 可以由库作者编写,以使用适合平台的块大小。

【讨论】:

  • 我希望std::equalmemcpy 快;编译器会为所涉及的精确类型生成它,甚至可能会考虑对齐之类的事情。 (当然,memcpy 可能只是 #define 之类的 __builtin_memcpy,因此编译器可以进行类似的优化。)
  • 是的,但是您关于边界对齐的建议绝对值得一试;如果它们在 32 字节块上对齐,则可能是一条 SSE 指令来检查它们...
  • @sarnold 是否有一个 SSE 指令可以精确比较 160 位? :) 您可能不得不从内存中过度读取(危险?),然后屏蔽掉多余的位。
  • @Fred:单个操作可能是乐观的,但您大概可以将其作为 128 和 32 如果您有正确的对齐方式。不幸的是,检查对齐可能比无条件地以较小的块进行检查需要更长的时间。
  • @Fred:我正在考虑将接下来的 12 个字节归零,这样它们就不会影响比较。我确实有点过分热心,并假设较新的 SSE* 指令可能会引入 256 位比较例程,但您是对的:看起来大多数 CPU 的比较指令最多用于 128 位块。虽然SSE 4.2 introduced some variable-length string comparison routines,但图书馆可能需要一段时间才能包含它们。
【解决方案3】:

std::equal 似乎是最好的选择,但memcmp 也可以。 关于效率,这将取决于实施,但 还(可能)如何定义和表示数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-22
    • 1970-01-01
    • 1970-01-01
    • 2017-03-28
    • 1970-01-01
    相关资源
    最近更新 更多