From 4fef9b88371acde819cd431f4e099e7e511606e4 Mon Sep 17 00:00:00 2001 From: Jeffrey Walton Date: Fri, 19 May 2017 23:29:59 -0400 Subject: [PATCH] Rework benchmark code This change moves test selections from test.cpp into bench.cpp. It also allows us finer control over test classes and algorithms --- bench.h | 11 ++++++++++- bench1.cpp | 38 +++++++++++++++++++++++++++++++++++--- regtest1.cpp | 4 +++- test.cpp | 48 +++--------------------------------------------- validate.h | 39 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 90 insertions(+), 50 deletions(-) diff --git a/bench.h b/bench.h index a30b22ef..d16f7462 100644 --- a/bench.h +++ b/bench.h @@ -14,7 +14,14 @@ NAMESPACE_BEGIN(CryptoPP) NAMESPACE_BEGIN(Test) -enum TestClass {Unkeyed=1,SharedKey=2,PublicKey=4, All=Unkeyed|SharedKey|PublicKey}; +// More granular control over benchmarks +enum TestClass { + Unkeyed=1,SharedKeyMAC=2,SharedKeyStream=4,SharedKeyBlock=8,SharedKeyOther=16, + PublicKeyAgreement=32,PublicKeyEncryption=64,PublicKeySignature=128,PublicKeyOther=256, + SharedKey=SharedKeyMAC|SharedKeyStream|SharedKeyBlock|SharedKeyOther, + PublicKey=PublicKeyAgreement|PublicKeyEncryption|PublicKeySignature|PublicKeyOther, + All=Unkeyed|SharedKey|PublicKey +}; extern const double CLOCK_TICKS_PER_SECOND; extern double g_allocatedTime; @@ -27,6 +34,8 @@ extern const byte defaultKey[]; extern time_t g_testBegin; extern time_t g_testEnd; +// Command handler +void BenchmarkWithCommand(int argc, const char* const argv[]); // Top level, prints preamble and postamble void Benchmark(Test::TestClass suites, double t, double hertz); // Unkeyed systems diff --git a/bench1.cpp b/bench1.cpp index 821aa08c..d288cdc7 100644 --- a/bench1.cpp +++ b/bench1.cpp @@ -339,6 +339,23 @@ void AddHtmlFooter() std::cout << "\n" << std::endl; } +void BenchmarkWithCommand(int argc, const char* const argv[]) +{ + std::string command(argv[1]); + float runningTime(argc >= 3 ? Test::StringToValue(argv[2]) : 1.0f); + float cpuFreq(argc >= 4 ? Test::StringToValue(argv[3])*float(1e9) : 0.0f); + std::string algoName(argc >= 5 ? argv[4] : ""); + + if (command == "b") // All benchmarks + Benchmark(Test::All, runningTime, cpuFreq); + else if (command == "b3") // Public key algorithms + Test::Benchmark(Test::PublicKey, runningTime, cpuFreq); + else if (command == "b2") // Shared key algorithms + Test::Benchmark(Test::SharedKey, runningTime, cpuFreq); + else if (command == "b1") // Unkeyed algorithms + Test::Benchmark(Test::Unkeyed, runningTime, cpuFreq); +} + void Benchmark(Test::TestClass suites, double t, double hertz) { g_allocatedTime = t; @@ -348,7 +365,7 @@ void Benchmark(Test::TestClass suites, double t, double hertz) g_testBegin = std::time(NULLPTR); - if (static_cast(suites) > 7 || static_cast(suites) == 0) + if (static_cast(suites) > 256 || static_cast(suites) == 0) suites = Test::All; // Unkeyed algorithms @@ -358,8 +375,22 @@ void Benchmark(Test::TestClass suites, double t, double hertz) Benchmark1(t, hertz); } - // Shared key algorithms - if (suites & Test::SharedKey) + // Shared key algorithms (MACs) + if (suites & Test::SharedKeyMAC) + { + std::cout << "\n
"; + Benchmark2(t, hertz); + } + + // Shared key algorithms (stream ciphers) + if (suites & Test::SharedKeyStream) + { + std::cout << "\n
"; + Benchmark2(t, hertz); + } + + // Shared key algorithms (block ciphers) + if (suites & Test::SharedKeyBlock) { std::cout << "\n
"; Benchmark2(t, hertz); @@ -399,6 +430,7 @@ void Benchmark1(double t, double hertz) cpb = ""; std::cout << "\n"; + std::cout << "\n"; std::cout << ""; std::cout << "\n
AlgorithmMiB/Second" << cpb; diff --git a/regtest1.cpp b/regtest1.cpp index 194f2898..c4eb7380 100644 --- a/regtest1.cpp +++ b/regtest1.cpp @@ -52,7 +52,9 @@ void RegisterFactories(Test::TestClass suites) if ((suites & Test::Unkeyed) == Test::Unkeyed) RegisterFactories1(); - if ((suites & Test::SharedKey) == Test::SharedKey) + if ((suites & Test::SharedKeyMAC) == Test::SharedKeyMAC || + (suites & Test::SharedKeyMAC) == Test::SharedKeyStream || + (suites & Test::SharedKeyMAC) == Test::SharedKeyBlock) RegisterFactories2(); if ((suites & Test::PublicKey) == Test::PublicKey) diff --git a/test.cpp b/test.cpp index d1a479df..b19fbad5 100644 --- a/test.cpp +++ b/test.cpp @@ -117,43 +117,6 @@ int (*AdhocTest)(int argc, char *argv[]) = NULLPTR; NAMESPACE_BEGIN(CryptoPP) NAMESPACE_BEGIN(Test) -// Coverity finding -template -T StringToValue(const std::string& str) -{ - std::istringstream iss(str); - - // Arbitrary, but we need to clear a Coverity finding TAINTED_SCALAR - if (iss.str().length() > 25) - throw InvalidArgument(str + "' is too long"); - - T value; - iss >> std::noskipws >> value; - - // Use fail(), not bad() - if (iss.fail() || !iss.eof()) - throw InvalidArgument(str + "' is not a value"); - - if (NON_NEGATIVE && value < 0) - throw InvalidArgument(str + "' is negative"); - - return value; -} - -// Coverity finding -template<> -int StringToValue(const std::string& str) -{ - Integer n(str.c_str()); - long l = n.ConvertToLong(); - - int r; - if (!SafeConvert(l, r)) - throw InvalidArgument(str + "' is not an integer value"); - - return r; -} - ANONYMOUS_NAMESPACE_BEGIN OFB_Mode::Encryption s_globalRNG; NAMESPACE_END @@ -399,14 +362,8 @@ int CRYPTOPP_API main(int argc, char *argv[]) InformationRecoverFile(argc-3, argv[2], argv+3); else if (command == "v" || command == "vv") return !Validate(argc>2 ? Test::StringToValue(argv[2]) : 0, argv[1][1] == 'v', argc>3 ? argv[3] : NULLPTR); - else if (command == "b") // All benchmarks - Test::Benchmark(Test::All, argc<3 ? 1 : Test::StringToValue(argv[2]), argc<4 ? 0.0f : Test::StringToValue(argv[3])*1e9); - else if (command == "b3") // Public key algorithms - Test::Benchmark(Test::PublicKey, argc<3 ? 1 : Test::StringToValue(argv[2]), argc<4 ? 0.0f : Test::StringToValue(argv[3])*1e9); - else if (command == "b2") // Shared key algorithms - Test::Benchmark(Test::SharedKey, argc<3 ? 1 : Test::StringToValue(argv[2]), argc<4 ? 0.0f : Test::StringToValue(argv[3])*1e9); - else if (command == "b1") // Unkeyed algorithms - Test::Benchmark(Test::Unkeyed, argc<3 ? 1 : Test::StringToValue(argv[2]), argc<4 ? 0.0f : Test::StringToValue(argv[3])*1e9); + else if (command.substr(0,1) == "b") // "b", "b1", "b2", ... + Test::BenchmarkWithCommand(argc, argv); else if (command == "z") GzipFile(argv[3], argv[4], argv[2][0]-'0'); else if (command == "u") @@ -435,6 +392,7 @@ int CRYPTOPP_API main(int argc, char *argv[]) { FileSource usage(CRYPTOPP_DATA_DIR "TestData/usage.dat", true, new FileSink(std::cout)); return 1; + return 1; } else if (command == "V") { diff --git a/validate.h b/validate.h index 8d2d4f46..e339bb01 100644 --- a/validate.h +++ b/validate.h @@ -5,6 +5,8 @@ #define CRYPTOPP_VALIDATE_H #include "cryptlib.h" +#include "integer.h" +#include "misc.h" #include #include @@ -207,6 +209,43 @@ inline std::string TimeToString(const time_t& t) return str; } +// Coverity finding +template +inline T StringToValue(const std::string& str) +{ + std::istringstream iss(str); + + // Arbitrary, but we need to clear a Coverity finding TAINTED_SCALAR + if (iss.str().length() > 25) + throw InvalidArgument(str + "' is too long"); + + T value; + iss >> std::noskipws >> value; + + // Use fail(), not bad() + if (iss.fail() || !iss.eof()) + throw InvalidArgument(str + "' is not a value"); + + if (NON_NEGATIVE && value < 0) + throw InvalidArgument(str + "' is negative"); + + return value; +} + +// Coverity finding +template<> +inline int StringToValue(const std::string& str) +{ + Integer n(str.c_str()); + long l = n.ConvertToLong(); + + int r; + if (!SafeConvert(l, r)) + throw InvalidArgument(str + "' is not an integer value"); + + return r; +} + // Functions that need a RNG; uses AES inf CFB mode with Seed. CryptoPP::RandomNumberGenerator & GlobalRNG();