问题描述
我正在寻找最快的SHA1实现,因为我必须对其进行数百万次的计算。我尝试了boost::uuids::detail::sha1和OpenSSL SHA1,并且我发现OpenSSL的速度是boost的2.5倍。我还检查了Crypto++,它比其他两个要慢得多。这是我检查他们表现的方法:
OpenSSL SHA1:
#include "openssl/sha.h"
void sha1_ossl (const unsigned char* data) {
unsigned char hash[20];
for (long i=0; i<100000000; ++i) {
SHA1(data,64,hash);
if ((unsigned int)hash[0]==0 && (unsigned int)hash[1]==0 && (unsigned int)hash[2]==0 && (unsigned int)hash[3]==0)
break;
}
}
Boost :: SHA1:
#include <boost/uuid/detail/sha1.hpp>
void sha1_boost (const unsigned char* data) {
boost::uuids::detail::sha1 sha1;
unsigned hash[5];
for (long i=0; i<100000000; ++i) {
sha1.process_bytes(data,64);
sha1.get_digest(hash);
sha1.reset();
if (hash[0]==0) break;
}
}
CryptoPP :: SHA1:
#include <cryptopp/sha.h>
#include <cryptopp/hex.h>
void sha1_cryptoPP (const unsigned char* data) {
std::string data_s (reinterpret_cast<char const*>(data));
std::string hash_hex;
CryptoPP::SHA1 sha1;
for (long i=0; i<100000000; ++i) {
CryptoPP::StringSource ss(data_s,true,new CryptoPP::HashFilter(sha1,new CryptoPP::HexEncoder(new CryptoPP::StringSink(hash_hex))));
if (hash_hex.starts_with("00000000")) break;
}
}
int main() {
const unsigned char data[65] = "tJQVfvcjGMNIvJfowXBjmSRcKtSjCcyQvaAdakfEJtgSNZHnOHCjkzGFwngiLFPm";
sha1_boost (data);
sha1_ossl (data);
sha1_cryptoPP (data);
}
效果结果
我用g++ -O3 -std=c++2a
编译了所有代码,以获得以下结果。我发现OpenSSL比其他实现更快,而Crypto ++最慢:
问题
- 最快的SHA1实现是什么?
- 如何改善我的Crypto ++功能?
感谢任何能改善性能的反馈。
解决方法
我的上一个实验证实,openssl的速度是其中几种最快的(包括Crypto ++以及一些我遗忘了哪些遗失的单源C实现)
Re:问题的代码审查类型部分:
-
增强的“实现”来自细节名称空间,不应依赖。
-
使用CryptoPP可能会受益于使用过程接口,而不是每次都动态地组成管道。具体来说,您不应转换为字符串来检查摘要的前n个字节。由于重复分配,这可能是运行时的主要部分。
遵循程序界面,还可以使您使用reset / clear成员(从内存中引用)
if ((unsigned int)hash[0] == 0 && (unsigned int)hash[1] == 0 &&
(unsigned int)hash[2] == 0 && (unsigned int)hash[3] == 0)
break;
应该很简单
if (!(hash[0] || hash[1] || hash[2] || hash[3]))
break;
甚至
if (!std::any_of(hash+0,hash+4,std::identity{}))
break;
改进的基准代码
结合了上述内容和更多内容(主要围绕良好的风格,避免指针错误,显示有效的迭代并允许dump
检查摘要的准确性)
#include "openssl/sha.h"
#include <boost/uuid/detail/sha1.hpp>
#include <algorithm>
#include <iostream>
#include <iomanip>
using byte = unsigned char;
#ifndef ONLINE_DEMO
auto constexpr iterations = 100'000'000;
#else
auto constexpr iterations = 10000;
#endif
static void dump(byte const (&a)[20]) {
for (unsigned b : a) {
std::cout << std::setw(2) << std::setfill('0') << std::hex << b;
}
std::cout << std::dec << std::endl;
}
static void dump(uint32_t const (&a)[5]) {
for (auto b : a) {
std::cout << std::setw(8) << std::setfill('0') << std::hex << b;
}
std::cout << std::dec << std::endl;
}
long sha1_ossl(std::string_view data) {
byte hash[20];
for (long i = 0; i < iterations; ++i) {
SHA1(reinterpret_cast<byte const*>(data.data()),data.size(),hash);
//dump(hash);
if (!std::any_of(hash+0,std::identity{}))
return i;
}
return iterations;
}
long sha1_boost(std::string_view data) {
boost::uuids::detail::sha1 sha1;
uint32_t hash[5];
for (long i = 0; i < iterations; ++i) {
sha1.process_bytes(reinterpret_cast<byte const*>(data.data()),data.size());
sha1.get_digest(hash);
sha1.reset();
//dump(hash);
if (hash[0] == 0)
return i;
}
return iterations;
}
#ifndef ONLINE_DEMO
#include <cryptopp/hex.h>
#include <cryptopp/sha.h>
long sha1_cryptoPP(std::string_view data) {
byte digest[20];
CryptoPP::SHA1 sha1;
for (long i = 0; i < iterations; ++i) {
sha1.Restart();
sha1.Update(reinterpret_cast<byte const*>(data.data()),data.size());
sha1.Final(digest);
//dump(digest);
if (!std::any_of(digest+0,digest+4,std::identity{}))
return i;
}
return iterations;
}
#endif
#include <chrono>
using namespace std::chrono_literals;
int main() {
static auto now = std::chrono::high_resolution_clock::now;
constexpr static std::string_view data =
"tJQVfvcjGMNIvJfowXBjmSRcKtSjCcyQvaAdakfEJtgSNZHnOHCjkzGFwngiLFPm";
auto timed = [](auto caption,auto f) {
auto const start = now();
auto n = f(data);
std::cout << caption << ": " << n << " in " << (now()-start)/1.0ms << "ms\n";
};
timed("sha1_boost",sha1_boost);
timed("sha1_ossl",sha1_ossl);
#ifndef ONLINE_DEMO
timed("sha1_cryptoPP",sha1_cryptoPP);
#endif
}
打印:
sha1_boost: 100000000 in 85660.5ms
sha1_ossl: 100000000 in 24652.6ms
sha1_cryptoPP: 100000000 in 34921.3ms
或在线(那里没有Crypto ++):
sha1_boost: 10000 in 8.71938ms
sha1_ossl: 10000 in 2.32025ms
这是一个很大的进步,但还是赢家。