Ali*_*Ali 5 c++ boost openssl crypto++
我正在寻找最快的 SHA1 实现,因为我必须对其进行数百万次计算。我尝试了boost::uuids::detail::sha1和OpenSSL SHA1,我发现 OpenSSL 比 boost 快 2.5 倍。我还检查了Crypto++,它比其他两个慢得多。以下是我检查他们表现的方法:
#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;
}
}
Run Code Online (Sandbox Code Playgroud)
#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;
}
}
Run Code Online (Sandbox Code Playgroud)
#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;
}
}
Run Code Online (Sandbox Code Playgroud)
然后我用随机数据测试这些函数:
int main() {
const unsigned char data[65] = "tJQVfvcjGMNIvJfowXBjmSRcKtSjCcyQvaAdakfEJtgSNZHnOHCjkzGFwngiLFPm";
sha1_boost (data);
sha1_ossl (data);
sha1_cryptoPP (data);
}
Run Code Online (Sandbox Code Playgroud)
我编译了所有代码以g++ -O3 -std=c++2a获得以下结果。我发现 OpenSSL 比其他实现更快,而 Crypto++ 最慢:
任何有助于提高性能的反馈都将受到赞赏。
我最近的实验证实 openssl 是几个中最快的(包括 Crypto++ 和一些丢失的单源 C 实现,我忘记了是哪一个)
回复:问题的代码审查类型部分:
boost“实现”来自详细名称空间,不应依赖。
CryptoPP 可能会受益于使用过程接口而不是每次动态组合管道。具体来说,您不应该转换为字符串来检查摘要的前 n 个字节。由于重复分配,这可能是运行时的主要部分。
遵循程序接口还可以允许您使用重置/清除成员(引用内存)
if ((unsigned int)hash[0] == 0 && (unsigned int)hash[1] == 0 &&
(unsigned int)hash[2] == 0 && (unsigned int)hash[3] == 0)
break;
Run Code Online (Sandbox Code Playgroud)
应该是一个简单的
if (!(hash[0] || hash[1] || hash[2] || hash[3]))
break;
Run Code Online (Sandbox Code Playgroud)
甚至
if (!std::any_of(hash+0, hash+4, std::identity{}))
break;
Run Code Online (Sandbox Code Playgroud)
结合上述一些内容和更多内容(主要围绕良好的风格,避免指针错误,显示有效的迭代并允许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, hash+4, 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
}
Run Code Online (Sandbox Code Playgroud)
印刷:
sha1_boost: 100000000 in 85660.5ms
sha1_ossl: 100000000 in 24652.6ms
sha1_cryptoPP: 100000000 in 34921.3ms
Run Code Online (Sandbox Code Playgroud)
或在线(没有 Crypto++):
sha1_boost: 10000 in 8.71938ms
sha1_ossl: 10000 in 2.32025ms
Run Code Online (Sandbox Code Playgroud)
这是一个显着的进步,但同样是赢家。
| 归档时间: |
|
| 查看次数: |
2109 次 |
| 最近记录: |