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
pull/242/merge
Jeffrey Walton 2017-05-19 23:29:59 -04:00
parent 82accdc13b
commit 4fef9b8837
No known key found for this signature in database
GPG Key ID: B36AB348921B1838
5 changed files with 90 additions and 50 deletions

11
bench.h
View File

@ -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

View File

@ -339,6 +339,23 @@ void AddHtmlFooter()
std::cout << "\n</HTML>" << std::endl;
}
void BenchmarkWithCommand(int argc, const char* const argv[])
{
std::string command(argv[1]);
float runningTime(argc >= 3 ? Test::StringToValue<float, true>(argv[2]) : 1.0f);
float cpuFreq(argc >= 4 ? Test::StringToValue<float, true>(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<int>(suites) > 7 || static_cast<int>(suites) == 0)
if (static_cast<int>(suites) > 256 || static_cast<int>(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<BR>";
Benchmark2(t, hertz);
}
// Shared key algorithms (stream ciphers)
if (suites & Test::SharedKeyStream)
{
std::cout << "\n<BR>";
Benchmark2(t, hertz);
}
// Shared key algorithms (block ciphers)
if (suites & Test::SharedKeyBlock)
{
std::cout << "\n<BR>";
Benchmark2(t, hertz);
@ -399,6 +430,7 @@ void Benchmark1(double t, double hertz)
cpb = "";
std::cout << "\n<TABLE>";
std::cout << "\n<COLGROUP><COL style=\"text-align: left;\"><COL style=\"text-align: right;\">";
std::cout << "<COL style=\"text-align: right;\">";
std::cout << "\n<THEAD style=\"background: #F0F0F0\"><TR><TH>Algorithm<TH>MiB/Second" << cpb;

View File

@ -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)

View File

@ -117,43 +117,6 @@ int (*AdhocTest)(int argc, char *argv[]) = NULLPTR;
NAMESPACE_BEGIN(CryptoPP)
NAMESPACE_BEGIN(Test)
// Coverity finding
template <class T, bool NON_NEGATIVE>
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<int, true>(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<AES>::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<int, true>(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<float, true>(argv[2]), argc<4 ? 0.0f : Test::StringToValue<float, true>(argv[3])*1e9);
else if (command == "b3") // Public key algorithms
Test::Benchmark(Test::PublicKey, argc<3 ? 1 : Test::StringToValue<float, true>(argv[2]), argc<4 ? 0.0f : Test::StringToValue<float, true>(argv[3])*1e9);
else if (command == "b2") // Shared key algorithms
Test::Benchmark(Test::SharedKey, argc<3 ? 1 : Test::StringToValue<float, true>(argv[2]), argc<4 ? 0.0f : Test::StringToValue<float, true>(argv[3])*1e9);
else if (command == "b1") // Unkeyed algorithms
Test::Benchmark(Test::Unkeyed, argc<3 ? 1 : Test::StringToValue<float, true>(argv[2]), argc<4 ? 0.0f : Test::StringToValue<float, true>(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")
{

View File

@ -5,6 +5,8 @@
#define CRYPTOPP_VALIDATE_H
#include "cryptlib.h"
#include "integer.h"
#include "misc.h"
#include <iostream>
#include <iomanip>
@ -207,6 +209,43 @@ inline std::string TimeToString(const time_t& t)
return str;
}
// Coverity finding
template <class T, bool NON_NEGATIVE>
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<int, true>(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();