26 #if CRYPTOPP_MSC_VERSION
27 # pragma warning(disable: 4355)
30 #if CRYPTOPP_MSC_VERSION
31 # pragma warning(disable: 4505 4355)
38 const double CLOCK_TICKS_PER_SECOND = (double)CLOCKS_PER_SEC;
39 #elif defined(CLK_TCK)
40 const double CLOCK_TICKS_PER_SECOND = (double)CLK_TCK;
42 const double CLOCK_TICKS_PER_SECOND = 1000000.0;
45 extern const byte defaultKey[] =
"0123456789"
46 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
47 "00000000000000000000000000000000000000000000000000000"
48 "00000000000000000000000000000000000000000000000000000";
50 double g_allocatedTime = 0.0, g_hertz = 0.0, g_logTotal = 0.0;
51 unsigned int g_logCount = 0;
52 time_t g_testBegin, g_testEnd;
54 inline std::string HertzToString(
double hertz)
56 std::ostringstream oss;
59 if (hertz >= 0.999e+9)
60 oss << hertz / 1e+9 <<
" GHz";
61 else if (hertz >= 0.999e+6)
62 oss << hertz / 1e+6 <<
" MHz";
63 else if (hertz >= 0.999e+3)
64 oss << hertz / 1e+3 <<
" KHz";
66 oss << hertz <<
" Hz";
71 void OutputResultBytes(
const char *name,
const char *provider,
double length,
double timeTaken)
73 std::ostringstream oss;
76 if (length < 0.000001f) length = 0.000001f;
77 if (timeTaken < 0.000001f) timeTaken = 0.000001f;
79 double mbs = length / timeTaken / (1024*1024);
80 oss <<
"\n<TR><TD>" << name <<
"<TD>" << provider;
81 oss << std::setiosflags(std::ios::fixed);
82 oss <<
"<TD>" << std::setprecision(0) << std::setiosflags(std::ios::fixed) << mbs;
85 const double cpb = timeTaken * g_hertz / length;
87 oss <<
"<TD>" << std::setprecision(2) << std::setiosflags(std::ios::fixed) << cpb;
89 oss <<
"<TD>" << std::setprecision(1) << std::setiosflags(std::ios::fixed) << cpb;
91 g_logTotal += log(mbs);
94 std::cout << oss.str();
97 void OutputResultKeying(
double iterations,
double timeTaken)
99 std::ostringstream oss;
102 if (iterations < 0.000001f) iterations = 0.000001f;
103 if (timeTaken < 0.000001f) timeTaken = 0.000001f;
105 oss <<
"<TD>" << std::setprecision(3) << std::setiosflags(std::ios::fixed) << (1000*1000*timeTaken/iterations);
109 oss <<
"<TD>" << std::setprecision(0) << std::setiosflags(std::ios::fixed) << timeTaken * g_hertz / iterations;
111 std::cout << oss.str();
114 void OutputResultOperations(
const char *name,
const char *provider,
const char *operation,
bool pc,
unsigned long iterations,
double timeTaken)
116 CRYPTOPP_UNUSED(provider);
117 std::ostringstream oss;
120 if (!iterations) iterations++;
121 if (timeTaken < 0.000001f) timeTaken = 0.000001f;
123 oss <<
"\n<TR><TD>" << name <<
" " << operation << (pc ?
" with precomputation" :
"");
125 oss <<
"<TD>" << std::setprecision(3) << std::setiosflags(std::ios::fixed) << (1000*timeTaken/iterations);
130 const double t = timeTaken * g_hertz / iterations / 1000000;
131 oss <<
"<TD>" << std::setprecision(3) << std::setiosflags(std::ios::fixed) << t;
134 g_logTotal += log(iterations/timeTaken);
137 std::cout << oss.str();
169 Test::GlobalRNG().GenerateBlock(buf, BUF_SIZE);
172 unsigned long i=0, blocks=1;
175 clock_t start = ::clock();
179 for (; i<blocks; i++)
181 timeTaken = double(::clock() - start) / CLOCK_TICKS_PER_SECOND;
183 while (timeTaken < 2.0/3*timeTotal);
186 OutputResultBytes(name, provider.c_str(),
double(blocks) * BUF_SIZE, timeTaken);
191 const int BUF_SIZE=2048U;
193 Test::GlobalRNG().GenerateBlock(buf, BUF_SIZE);
196 unsigned long i=0, blocks=1;
199 clock_t start = ::clock();
203 for (; i<blocks; i++)
205 timeTaken = double(::clock() - start) / CLOCK_TICKS_PER_SECOND;
207 while (timeTaken < 2.0/3*timeTotal);
210 OutputResultBytes(name, provider.c_str(),
double(blocks) * BUF_SIZE, timeTaken);
215 const int BUF_SIZE=2048U;
217 Test::GlobalRNG().GenerateBlock(buf, BUF_SIZE);
220 unsigned long i=0, blocks=1;
223 clock_t start = ::clock();
227 for (; i<blocks; i++)
228 bt.
Put(buf, BUF_SIZE);
229 timeTaken = double(::clock() - start) / CLOCK_TICKS_PER_SECOND;
231 while (timeTaken < 2.0/3*timeTotal);
234 OutputResultBytes(name, provider.c_str(),
double(blocks) * BUF_SIZE, timeTaken);
239 const int BUF_SIZE = 2048U;
241 Test::GlobalRNG().GenerateBlock(buf, BUF_SIZE);
245 if (cipher != NULLPTR)
251 cipher->
SetKey(buf, size);
254 unsigned long long blocks = 1;
257 clock_t start = ::clock();
262 timeTaken = double(::clock() - start) / CLOCK_TICKS_PER_SECOND;
263 }
while (timeTaken < timeTotal);
266 OutputResultBytes(name, provider.c_str(),
double(blocks) * BUF_SIZE, timeTaken);
273 void BenchMark(
const char *name,
NIST_DRBG &rng,
double timeTotal)
275 const int BUF_SIZE = 2048U;
277 Test::GlobalRNG().GenerateBlock(buf, BUF_SIZE);
281 unsigned long long blocks = 1;
284 clock_t start = ::clock();
289 timeTaken = double(::clock() - start) / CLOCK_TICKS_PER_SECOND;
290 }
while (timeTaken < timeTotal);
293 OutputResultBytes(name, provider.c_str(),
double(blocks) * BUF_SIZE, timeTaken);
299 CRYPTOPP_UNUSED(params);
300 std::string name = factoryName;
305 BenchMark(name.c_str(), *obj, g_allocatedTime);
310 std::ostringstream oss;
313 oss <<
"<!DOCTYPE HTML>";
314 oss <<
"\n<HTML lang=\"en\">";
317 oss <<
"\n<META charset=\"UTF-8\">";
318 oss <<
"\n<TITLE>Speed Comparison of Popular Crypto Algorithms</TITLE>";
319 oss <<
"\n<STYLE>\n table {border-collapse: collapse;}";
320 oss <<
"\n table, th, td, tr {border: 1px solid black;}\n</STYLE>";
325 oss <<
"\n<H1><A href=\"http://www.cryptopp.com\">Crypto++</A> " << CRYPTOPP_VERSION / 100;
326 oss <<
'.' << (CRYPTOPP_VERSION % 100) / 10 <<
'.' << CRYPTOPP_VERSION % 10 <<
" Benchmarks</H1>";
328 oss <<
"\n<P>Here are speed benchmarks for some commonly used cryptographic algorithms.</P>";
331 oss <<
"\n<P>CPU frequency of the test platform is " << HertzToString(g_hertz) <<
".</P>";
333 oss <<
"\n<P>CPU frequency of the test platform was not provided.</P>" << std::endl;
335 std::cout << oss.str();
340 std::ostringstream oss;
341 oss <<
"\n</BODY>\n</HTML>\n";
342 std::cout << oss.str();
345 void BenchmarkWithCommand(
int argc,
const char*
const argv[])
347 std::string command(argv[1]);
348 float runningTime(argc >= 3 ? Test::StringToValue<float, true>(argv[2]) : 1.0f);
349 float cpuFreq(argc >= 4 ? Test::StringToValue<float, true>(argv[3])*
float(1e9) : 0.0f);
350 std::string algoName(argc >= 5 ? argv[4] :
"");
353 if (runningTime > 10.0f)
357 Benchmark(Test::All, runningTime, cpuFreq);
358 else if (command ==
"b4")
359 Test::Benchmark(Test::PublicKeyEC, runningTime, cpuFreq);
360 else if (command ==
"b3")
361 Test::Benchmark(Test::PublicKey, runningTime, cpuFreq);
362 else if (command ==
"b2")
363 Test::Benchmark(Test::SharedKey, runningTime, cpuFreq);
364 else if (command ==
"b1")
365 Test::Benchmark(Test::Unkeyed, runningTime, cpuFreq);
368 void Benchmark(Test::TestClass suites,
double t,
double hertz)
374 size_t count_breaks = 0;
378 g_testBegin = ::time(NULLPTR);
380 if (
static_cast<int>(suites) == 0 ||
static_cast<int>(suites) > TestLast)
384 if (suites & Test::Unkeyed)
387 std::cout <<
"\n<BR>";
390 BenchmarkUnkeyedAlgorithms(t, hertz);
394 if (suites & Test::SharedKey)
397 std::cout <<
"\n<BR>";
400 BenchmarkSharedKeyedAlgorithms(t, hertz);
404 if (suites & Test::PublicKey)
407 std::cout <<
"\n<BR>";
410 BenchmarkPublicKeyAlgorithms(t, hertz);
414 if (suites & Test::PublicKeyEC)
417 std::cout <<
"\n<BR>";
420 BenchmarkEllipticCurveAlgorithms(t, hertz);
423 g_testEnd = ::time(NULLPTR);
425 std::ostringstream oss;
426 oss <<
"\n<P>Throughput Geometric Average: " << std::setiosflags(std::ios::fixed);
427 oss << std::exp(g_logTotal/(g_logCount > 0.0f ? g_logCount : 1.0f)) << std::endl;
429 oss <<
"\n<P>Test started at " << TimeToString(g_testBegin);
430 oss <<
"\n<BR>Test ended at " << TimeToString(g_testEnd);
432 std::cout << oss.str();
437 void BenchmarkUnkeyedAlgorithms(
double t,
double hertz)
444 cpb =
"<TH>Cycles/Byte";
448 std::cout <<
"\n<TABLE>";
450 std::cout <<
"\n<COLGROUP><COL style=\"text-align: left;\"><COL style=\"text-align: right;\">";
451 std::cout <<
"<COL style=\"text-align: right;\">";
452 std::cout <<
"\n<THEAD style=\"background: #F0F0F0\">";
453 std::cout <<
"\n<TR><TH>Algorithm<TH>Provider<TH>MiB/Second" << cpb;
455 std::cout <<
"\n<TBODY style=\"background: white;\">";
457 #ifdef NONBLOCKING_RNG_AVAILABLE
458 BenchMarkByNameKeyLess<RandomNumberGenerator>(
"NonblockingRng");
460 #ifdef OS_RNG_AVAILABLE
461 BenchMarkByNameKeyLess<RandomNumberGenerator>(
"AutoSeededRandomPool");
462 BenchMarkByNameKeyLess<RandomNumberGenerator>(
"AutoSeededX917RNG(AES)");
464 BenchMarkByNameKeyLess<RandomNumberGenerator>(
"MT19937");
465 #if (CRYPTOPP_BOOL_X86) && !defined(CRYPTOPP_DISABLE_ASM)
467 BenchMarkByNameKeyLess<RandomNumberGenerator>(
"PadlockRNG");
469 #if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64) && !defined(CRYPTOPP_DISABLE_ASM)
471 BenchMarkByNameKeyLess<RandomNumberGenerator>(
"RDRAND");
473 BenchMarkByNameKeyLess<RandomNumberGenerator>(
"RDSEED");
475 #if (CRYPTOPP_BOOL_PPC32 || CRYPTOPP_BOOL_PPC64) && !defined(CRYPTOPP_DISABLE_ASM)
477 BenchMarkByNameKeyLess<RandomNumberGenerator>(
"DARN");
479 BenchMarkByNameKeyLess<RandomNumberGenerator>(
"AES/OFB RNG");
480 BenchMarkByNameKeyLess<NIST_DRBG>(
"Hash_DRBG(SHA1)");
481 BenchMarkByNameKeyLess<NIST_DRBG>(
"Hash_DRBG(SHA256)");
482 BenchMarkByNameKeyLess<NIST_DRBG>(
"HMAC_DRBG(SHA1)");
483 BenchMarkByNameKeyLess<NIST_DRBG>(
"HMAC_DRBG(SHA256)");
486 std::cout <<
"\n<TBODY style=\"background: yellow;\">";
488 BenchMarkByNameKeyLess<HashTransformation>(
"CRC32");
489 BenchMarkByNameKeyLess<HashTransformation>(
"CRC32C");
490 BenchMarkByNameKeyLess<HashTransformation>(
"Adler32");
491 BenchMarkByNameKeyLess<HashTransformation>(
"MD5");
492 BenchMarkByNameKeyLess<HashTransformation>(
"SHA-1");
493 BenchMarkByNameKeyLess<HashTransformation>(
"SHA-256");
494 BenchMarkByNameKeyLess<HashTransformation>(
"SHA-512");
495 BenchMarkByNameKeyLess<HashTransformation>(
"SHA3-224");
496 BenchMarkByNameKeyLess<HashTransformation>(
"SHA3-256");
497 BenchMarkByNameKeyLess<HashTransformation>(
"SHA3-384");
498 BenchMarkByNameKeyLess<HashTransformation>(
"SHA3-512");
499 BenchMarkByNameKeyLess<HashTransformation>(
"Keccak-224");
500 BenchMarkByNameKeyLess<HashTransformation>(
"Keccak-256");
501 BenchMarkByNameKeyLess<HashTransformation>(
"Keccak-384");
502 BenchMarkByNameKeyLess<HashTransformation>(
"Keccak-512");
503 BenchMarkByNameKeyLess<HashTransformation>(
"Tiger");
504 BenchMarkByNameKeyLess<HashTransformation>(
"Whirlpool");
505 BenchMarkByNameKeyLess<HashTransformation>(
"RIPEMD-160");
506 BenchMarkByNameKeyLess<HashTransformation>(
"RIPEMD-320");
507 BenchMarkByNameKeyLess<HashTransformation>(
"RIPEMD-128");
508 BenchMarkByNameKeyLess<HashTransformation>(
"RIPEMD-256");
509 BenchMarkByNameKeyLess<HashTransformation>(
"SM3");
510 BenchMarkByNameKeyLess<HashTransformation>(
"BLAKE2s");
511 BenchMarkByNameKeyLess<HashTransformation>(
"BLAKE2b");
514 std::cout <<
"\n</TABLE>" << std::endl;