- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

# bench.cpp

    00001 // bench.cpp - written and placed in the public domain by Wei Dai
    00002
    00003 #define _CRT_SECURE_NO_DEPRECATE
    00004
    00005 #include "bench.h"
    00006 #include "crc.h"
    00007 #include "adler32.h"
    00008 #include "idea.h"
    00009 #include "des.h"
    00010 #include "rc5.h"
    00011 #include "blowfish.h"
    00012 #include "wake.h"
    00013 #include "cast.h"
    00014 #include "seal.h"
    00015 #include "rc6.h"
    00016 #include "mars.h"
    00017 #include "twofish.h"
    00018 #include "serpent.h"
    00019 #include "skipjack.h"
    00020 #include "cbcmac.h"
    00021 #include "dmac.h"
    00022 #include "aes.h"
    00023 #include "blumshub.h"
    00024 #include "rng.h"
    00025 #include "files.h"
    00026 #include "hex.h"
    00027 #include "modes.h"
    00028 #include "factory.h"
    00029
    00030 #include <time.h>
    00031 #include <math.h>
    00032 #include <iostream>
    00033 #include <iomanip>
    00034
    00035 USING_NAMESPACE(CryptoPP)
    00036 USING_NAMESPACE(std)
    00037
    00038 #ifdef CLOCKS_PER_SEC
    00039 const double CLOCK_TICKS_PER_SECOND = (double)CLOCKS_PER_SEC;
    00040 #elif defined(CLK_TCK)
    00041 const double CLOCK_TICKS_PER_SECOND = (double)CLK_TCK;
    00042 #else
    00043 const double CLOCK_TICKS_PER_SECOND = 1000000.0;
    00044 #endif
    00045
    00046 double logtotal = 0, g_allocatedTime, g_hertz;
    00047 unsigned int logcount = 0;
    00048
    00049 static const byte *const key=(byte *)"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
    00050
    00051 void OutputResultBytes(const char *name, double length, double timeTaken)
    00052 {
    00053         double mbs = length / timeTaken / (1024*1024);
    00054         cout << "\n<TR><TH>" << name;
    00055 //      cout << "<TD>" << setprecision(3) << length / (1024*1024);
    00056         cout << setiosflags(ios::fixed);
    00057 //      cout << "<TD>" << setprecision(3) << timeTaken;
    00058         cout << "<TD>" << setprecision(0) << setiosflags(ios::fixed) << mbs;
    00059         if (g_hertz)
    00060                 cout << "<TD>" << setprecision(1) << setiosflags(ios::fixed) << timeTaken * g_hertz / length;
    00061         cout << resetiosflags(ios::fixed);
    00062         logtotal += log(mbs);
    00063         logcount++;
    00064 }
    00065
    00066 void OutputResultKeying(double iterations, double timeTaken)
    00067 {
    00068         cout << "<TD>" << setprecision(3) << setiosflags(ios::fixed) << (1000*1000*timeTaken/iterations);
    00069         if (g_hertz)
    00070                 cout << "<TD>" << setprecision(0) << setiosflags(ios::fixed) << timeTaken * g_hertz / iterations;
    00071 }
    00072
    00073 void OutputResultOperations(const char *name, const char *operation, bool pc, unsigned long iterations, double timeTaken)
    00074 {
    00075         cout << "\n<TR><TH>" << name << " " << operation << (pc ? " with precomputation" : "");
    00076 //      cout << "<TD>" << iterations;
    00077 //      cout << setiosflags(ios::fixed);
    00078 //      cout << "<TD>" << setprecision(3) << timeTaken;
    00079         cout << "<TD>" << setprecision(2) << setiosflags(ios::fixed) << (1000*timeTaken/iterations);
    00080         if (g_hertz)
    00081                 cout << "<TD>" << setprecision(2) << setiosflags(ios::fixed) << timeTaken * g_hertz / iterations / 1000000;
    00082         cout << resetiosflags(ios::fixed);
    00083
    00084         logtotal += log(iterations/timeTaken);
    00085         logcount++;
    00086 }
    00087
    00088 void BenchMark(const char *name, BlockTransformation &cipher, double timeTotal)
    00089 {
    00090         const int BUF_SIZE = RoundUpToMultipleOf(2048U, cipher.OptimalNumberOfParallelBlocks() * cipher.BlockSize());
    00091         AlignedSecByteBlock buf(BUF_SIZE);
    00092         const int nBlocks = BUF_SIZE / cipher.BlockSize();
    00093         clock_t start = clock();
    00094
    00095         unsigned long i=0, blocks=1;
    00096         double timeTaken;
    00097         do
    00098         {
    00099                 blocks *= 2;
    00100                 for (; i<blocks; i++)
    00101                         cipher.ProcessAndXorMultipleBlocks(buf, NULL, buf, nBlocks);
    00102                 timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND;
    00103         }
    00104         while (timeTaken < 2.0/3*timeTotal);
    00105
    00106         OutputResultBytes(name, double(blocks) * BUF_SIZE, timeTaken);
    00107 }
    00108
    00109 void BenchMark(const char *name, StreamTransformation &cipher, double timeTotal)
    00110 {
    00111         const int BUF_SIZE=RoundUpToMultipleOf(2048U, cipher.OptimalBlockSize());
    00112         AlignedSecByteBlock buf(BUF_SIZE);
    00113         clock_t start = clock();
    00114
    00115         unsigned long i=0, blocks=1;
    00116         double timeTaken;
    00117         do
    00118         {
    00119                 blocks *= 2;
    00120                 for (; i<blocks; i++)
    00121                         cipher.ProcessString(buf, BUF_SIZE);
    00122                 timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND;
    00123         }
    00124         while (timeTaken < 2.0/3*timeTotal);
    00125
    00126         OutputResultBytes(name, double(blocks) * BUF_SIZE, timeTaken);
    00127 }
    00128
    00129 void BenchMark(const char *name, HashTransformation &ht, double timeTotal)
    00130 {
    00131         const int BUF_SIZE=2048U;
    00132         AlignedSecByteBlock buf(BUF_SIZE);
    00133         LC_RNG rng((word32)time(NULL));
    00134         rng.GenerateBlock(buf, BUF_SIZE);
    00135         clock_t start = clock();
    00136
    00137         unsigned long i=0, blocks=1;
    00138         double timeTaken;
    00139         do
    00140         {
    00141                 blocks *= 2;
    00142                 for (; i<blocks; i++)
    00143                         ht.Update(buf, BUF_SIZE);
    00144                 timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND;
    00145         }
    00146         while (timeTaken < 2.0/3*timeTotal);
    00147
    00148         OutputResultBytes(name, double(blocks) * BUF_SIZE, timeTaken);
    00149 }
    00150
    00151 void BenchMark(const char *name, BufferedTransformation &bt, double timeTotal)
    00152 {
    00153         const int BUF_SIZE=2048U;
    00154         AlignedSecByteBlock buf(BUF_SIZE);
    00155         LC_RNG rng((word32)time(NULL));
    00156         rng.GenerateBlock(buf, BUF_SIZE);
    00157         clock_t start = clock();
    00158
    00159         unsigned long i=0, blocks=1;
    00160         double timeTaken;
    00161         do
    00162         {
    00163                 blocks *= 2;
    00164                 for (; i<blocks; i++)
    00165                         bt.Put(buf, BUF_SIZE);
    00166                 timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND;
    00167         }
    00168         while (timeTaken < 2.0/3*timeTotal);
    00169
    00170         OutputResultBytes(name, double(blocks) * BUF_SIZE, timeTaken);
    00171 }
    00172
    00173 void BenchMarkKeying(SimpleKeyingInterface &c, size_t keyLength, const NameValuePairs &params)
    00174 {
    00175         unsigned long iterations = 0;
    00176         clock_t start = clock();
    00177         double timeTaken;
    00178         do
    00179         {
    00180                 for (unsigned int i=0; i<1024; i++)
    00181                         c.SetKey(key, keyLength, params);
    00182                 timeTaken = double(clock() - start) / CLOCK_TICKS_PER_SECOND;
    00183                 iterations += 1024;
    00184         }
    00185         while (timeTaken < g_allocatedTime);
    00186
    00187         OutputResultKeying(iterations, timeTaken);
    00188 }
    00189
    00190 //VC60 workaround: compiler bug triggered without the extra dummy parameters
    00191 template <class T>
    00192 void BenchMarkKeyed(const char *name, double timeTotal, const NameValuePairs &params = g_nullNameValuePairs, T *x=NULL)
    00193 {
    00194         T c;
    00195         c.SetKey(key, c.DefaultKeyLength(), CombinedNameValuePairs(params, MakeParameters(Name::IV(), key, false)));
    00196         BenchMark(name, c, timeTotal);
    00197         BenchMarkKeying(c, c.DefaultKeyLength(), CombinedNameValuePairs(params, MakeParameters(Name::IV(), key, false)));
    00198 }
    00199
    00200 //VC60 workaround: compiler bug triggered without the extra dummy parameters
    00201 template <class T>
    00202 void BenchMarkKeyedVariable(const char *name, double timeTotal, unsigned int keyLength, const NameValuePairs &params = g_nullNameValuePairs, T *x=NULL)
    00203 {
    00204         T c;
    00205         c.SetKey(key, keyLength, CombinedNameValuePairs(params, MakeParameters(Name::IV(), key, false)));
    00206         BenchMark(name, c, timeTotal);
    00207         BenchMarkKeying(c, keyLength, CombinedNameValuePairs(params, MakeParameters(Name::IV(), key, false)));
    00208 }
    00209
    00210 //VC60 workaround: compiler bug triggered without the extra dummy parameters
    00211 template <class T>
    00212 void BenchMarkKeyless(const char *name, double timeTotal, T *x=NULL)
    00213 {
    00214         T c;
    00215         BenchMark(name, c, timeTotal);
    00216 }
    00217
    00218 //VC60 workaround: compiler bug triggered without the extra dummy parameters
    00219 template <class T>
    00220 void BenchMarkByName(const char *factoryName, size_t keyLength = 0, const char *displayName=NULL, const NameValuePairs &params = g_nullNameValuePairs, T *x=NULL)
    00221 {
    00222         std::string name = factoryName;
    00223         if (displayName)
    00224                 name = displayName;
    00225         else if (keyLength)
    00226                 name += " (" + IntToString(keyLength * 8) + "-bit key)";
    00227
    00228         std::auto_ptr<T> obj(ObjectFactoryRegistry<T>::Registry().CreateObject(factoryName));
    00229         if (!keyLength)
    00230                 keyLength = obj->DefaultKeyLength();
    00231         obj->SetKey(key, keyLength, CombinedNameValuePairs(params, MakeParameters(Name::IV(), key, false)));
    00232         BenchMark(name.c_str(), *obj, g_allocatedTime);
    00233         BenchMarkKeying(*obj, keyLength, CombinedNameValuePairs(params, MakeParameters(Name::IV(), key, false)));
    00234 }
    00235
    00236 template <class T>
    00237 void BenchMarkByNameKeyLess(const char *factoryName, const char *displayName=NULL, const NameValuePairs &params = g_nullNameValuePairs, T *x=NULL)
    00238 {
    00239         std::string name = factoryName;
    00240         if (displayName)
    00241                 name = displayName;
    00242
    00243         std::auto_ptr<T> obj(ObjectFactoryRegistry<T>::Registry().CreateObject(factoryName));
    00244         BenchMark(name.c_str(), *obj, g_allocatedTime);
    00245 }
    00246
    00247 void BenchmarkAll(double t, double hertz)
    00248 {
    00249 #if 1
    00250         logtotal = 0;
    00251         logcount = 0;
    00252         g_allocatedTime = t;
    00253         g_hertz = hertz;
    00254
    00255         const char *cpb, *cpk;
    00256         if (g_hertz)
    00257         {
    00258                 cpb = "<TH>Cycles Per Byte";
    00259                 cpk = "<TH>Cycles to<br>Setup Key and IV";
    00260                 cout << "CPU frequency of the test platform is " << g_hertz << " Hz.\n";
    00261         }
    00262         else
    00263         {
    00264                 cpb = cpk = "";
    00265                 cout << "CPU frequency of the test platform was not provided.\n";
    00266         }
    00267
    00268         cout << "<TABLE border=1><COLGROUP><COL align=left><COL align=right><COL align=right><COL align=right><COL align=right>" << endl;
    00269         cout << "<THEAD><TR><TH>Algorithm<TH>MiB/Second" << cpb << "<TH>Microseconds to<br>Setup Key and IV" << cpk << endl;
    00270
    00271         cout << "\n<TBODY style=\"background: white\">";
    00272         BenchMarkByName<MessageAuthenticationCode>("VMAC(AES)-64");
    00273         BenchMarkByName<MessageAuthenticationCode>("VMAC(AES)-128");
    00274         BenchMarkByName<MessageAuthenticationCode>("HMAC(SHA-1)");
    00275         BenchMarkByName<MessageAuthenticationCode>("Two-Track-MAC");
    00276         BenchMarkKeyed<CBC_MAC<AES> >("CBC-MAC/AES", t);
    00277         BenchMarkKeyed<DMAC<AES> >("DMAC/AES", t);
    00278
    00279         cout << "\n<TBODY style=\"background: yellow\">";
    00280         BenchMarkKeyless<CRC32>("CRC-32", t);
    00281         BenchMarkKeyless<Adler32>("Adler-32", t);
    00282         BenchMarkByNameKeyLess<HashTransformation>("MD5");
    00283         BenchMarkByNameKeyLess<HashTransformation>("SHA-1");
    00284         BenchMarkByNameKeyLess<HashTransformation>("SHA-256");
    00285 #ifdef WORD64_AVAILABLE
    00286         BenchMarkByNameKeyLess<HashTransformation>("SHA-512");
    00287         BenchMarkByNameKeyLess<HashTransformation>("Tiger");
    00288         BenchMarkByNameKeyLess<HashTransformation>("Whirlpool");
    00289 #endif
    00290         BenchMarkByNameKeyLess<HashTransformation>("RIPEMD-160");
    00291         BenchMarkByNameKeyLess<HashTransformation>("RIPEMD-320");
    00292         BenchMarkByNameKeyLess<HashTransformation>("RIPEMD-128");
    00293         BenchMarkByNameKeyLess<HashTransformation>("RIPEMD-256");
    00294
    00295         cout << "\n<TBODY style=\"background: white\">";
    00296         BenchMarkByName<SymmetricCipher>("Panama-LE");
    00297         BenchMarkByName<SymmetricCipher>("Panama-BE");
    00298         BenchMarkByName<SymmetricCipher>("Salsa20");
    00299         BenchMarkByName<SymmetricCipher>("Salsa20", 0, "Salsa20/12", MakeParameters(Name::Rounds(), 12));
    00300         BenchMarkByName<SymmetricCipher>("Salsa20", 0, "Salsa20/8", MakeParameters(Name::Rounds(), 8));
    00301         BenchMarkByName<SymmetricCipher>("Sosemanuk");
    00302         BenchMarkByName<SymmetricCipher>("MARC4");
    00303         BenchMarkKeyed<SEAL<BigEndian>::Encryption>("SEAL-3.0-BE", t);
    00304         BenchMarkKeyed<SEAL<LittleEndian>::Encryption>("SEAL-3.0-LE", t);
    00305         BenchMarkKeyed<WAKE_OFB<BigEndian>::Encryption>("WAKE-OFB-BE", t);
    00306         BenchMarkKeyed<WAKE_OFB<LittleEndian>::Encryption>("WAKE-OFB-LE", t);
    00307
    00308         cout << "\n<TBODY style=\"background: yellow\">";
    00309         BenchMarkByName<SymmetricCipher>("AES/ECB", 16);
    00310         BenchMarkByName<SymmetricCipher>("AES/ECB", 24);
    00311         BenchMarkByName<SymmetricCipher>("AES/ECB", 32);
    00312         BenchMarkByName<SymmetricCipher>("AES/CTR", 16);
    00313         BenchMarkByName<SymmetricCipher>("AES/OFB", 16);
    00314         BenchMarkByName<SymmetricCipher>("AES/CFB", 16);
    00315         BenchMarkByName<SymmetricCipher>("AES/CBC", 16);
    00316         BenchMarkByName<SymmetricCipher>("Camellia/ECB", 16);
    00317         BenchMarkByName<SymmetricCipher>("Camellia/ECB", 32);
    00318         BenchMarkKeyed<Twofish::Encryption>("Twofish", t);
    00319         BenchMarkKeyed<Serpent::Encryption>("Serpent", t);
    00320         BenchMarkKeyed<CAST256::Encryption>("CAST-256", t);
    00321         BenchMarkKeyed<RC6::Encryption>("RC6", t);
    00322         BenchMarkKeyed<MARS::Encryption>("MARS", t);
    00323         BenchMarkByName<SymmetricCipher>("SHACAL-2/ECB", 16);
    00324         BenchMarkByName<SymmetricCipher>("SHACAL-2/ECB", 64);
    00325         BenchMarkKeyed<DES::Encryption>("DES", t);
    00326         BenchMarkKeyed<DES_XEX3::Encryption>("DES-XEX3", t);
    00327         BenchMarkKeyed<DES_EDE3::Encryption>("DES-EDE3", t);
    00328         BenchMarkKeyed<IDEA::Encryption>("IDEA", t);
    00329         BenchMarkKeyed<RC5::Encryption>("RC5 (r=16)", t);
    00330         BenchMarkKeyed<Blowfish::Encryption>("Blowfish", t);
    00331         BenchMarkByName<SymmetricCipher>("TEA/ECB");
    00332         BenchMarkByName<SymmetricCipher>("XTEA/ECB");
    00333         BenchMarkKeyed<CAST128::Encryption>("CAST-128", t);
    00334         BenchMarkKeyed<SKIPJACK::Encryption>("SKIPJACK", t);
    00335         cout << "</TABLE>" << endl;
    00336
    00337         BenchmarkAll2(t, hertz);
    00338
    00339         cout << "Throughput Geometric Average: " << setiosflags(ios::fixed) << exp(logtotal/logcount) << endl;
    00340
    00341         time_t endTime = time(NULL);
    00342         cout << "\nTest ended at " << asctime(localtime(&endTime));
    00343 #endif
    00344 }