Home | History | Annotate | Download | only in Console
      1 // BenchCon.cpp
      2 
      3 #include "StdAfx.h"
      4 
      5 #include "../../../Common/IntToString.h"
      6 #include "../../../Common/MyCom.h"
      7 
      8 #if !defined(_7ZIP_ST) || defined(_WIN32)
      9 #include "../../../Windows/System.h"
     10 #endif
     11 
     12 #include "../Common/Bench.h"
     13 
     14 #include "BenchCon.h"
     15 #include "ConsoleClose.h"
     16 
     17 struct CTotalBenchRes
     18 {
     19   UInt64 NumIterations;
     20   UInt64 Rating;
     21   UInt64 Usage;
     22   UInt64 RPU;
     23   void Init() { NumIterations = 0; Rating = 0; Usage = 0; RPU = 0; }
     24   void Normalize()
     25   {
     26     if (NumIterations == 0)
     27       return;
     28     Rating /= NumIterations;
     29     Usage /= NumIterations;
     30     RPU /= NumIterations;
     31     NumIterations = 1;
     32   }
     33   void SetMid(const CTotalBenchRes &r1, const CTotalBenchRes &r2)
     34   {
     35     Rating = (r1.Rating + r2.Rating) / 2;
     36     Usage = (r1.Usage + r2.Usage) / 2;
     37     RPU = (r1.RPU + r2.RPU) / 2;
     38     NumIterations = (r1.NumIterations + r2.NumIterations) / 2;
     39   }
     40 };
     41 
     42 struct CBenchCallback: public IBenchCallback
     43 {
     44   CTotalBenchRes EncodeRes;
     45   CTotalBenchRes DecodeRes;
     46   FILE *f;
     47   void Init() { EncodeRes.Init(); DecodeRes.Init(); }
     48   void Normalize() { EncodeRes.Normalize(); DecodeRes.Normalize(); }
     49   UInt32 dictionarySize;
     50   HRESULT SetEncodeResult(const CBenchInfo &info, bool final);
     51   HRESULT SetDecodeResult(const CBenchInfo &info, bool final);
     52 };
     53 
     54 static void NormalizeVals(UInt64 &v1, UInt64 &v2)
     55 {
     56   while (v1 > 1000000)
     57   {
     58     v1 >>= 1;
     59     v2 >>= 1;
     60   }
     61 }
     62 
     63 static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq)
     64 {
     65   UInt64 elTime = elapsedTime;
     66   NormalizeVals(freq, elTime);
     67   if (elTime == 0)
     68     elTime = 1;
     69   return value * freq / elTime;
     70 }
     71 
     72 static void PrintNumber(FILE *f, UInt64 value, int size)
     73 {
     74   char s[32];
     75   ConvertUInt64ToString(value, s);
     76   fprintf(f, " ");
     77   for (int len = (int)strlen(s); len < size; len++)
     78     fprintf(f, " ");
     79   fputs(s, f);
     80 }
     81 
     82 static void PrintRating(FILE *f, UInt64 rating)
     83 {
     84   PrintNumber(f, rating / 1000000, 6);
     85 }
     86 
     87 static void PrintResults(FILE *f, UInt64 usage, UInt64 rpu, UInt64 rating)
     88 {
     89   PrintNumber(f, (usage + 5000) / 10000, 5);
     90   PrintRating(f, rpu);
     91   PrintRating(f, rating);
     92 }
     93 
     94 
     95 static void PrintResults(FILE *f, const CBenchInfo &info, UInt64 rating, CTotalBenchRes &res)
     96 {
     97   UInt64 speed = MyMultDiv64(info.UnpackSize, info.GlobalTime, info.GlobalFreq);
     98   PrintNumber(f, speed / 1024, 7);
     99   UInt64 usage = GetUsage(info);
    100   UInt64 rpu = GetRatingPerUsage(info, rating);
    101   PrintResults(f, usage, rpu, rating);
    102   res.NumIterations++;
    103   res.RPU += rpu;
    104   res.Rating += rating;
    105   res.Usage += usage;
    106 }
    107 
    108 static void PrintTotals(FILE *f, const CTotalBenchRes &res)
    109 {
    110   fprintf(f, "       ");
    111   PrintResults(f, res.Usage, res.RPU, res.Rating);
    112 }
    113 
    114 
    115 HRESULT CBenchCallback::SetEncodeResult(const CBenchInfo &info, bool final)
    116 {
    117   if (NConsoleClose::TestBreakSignal())
    118     return E_ABORT;
    119   if (final)
    120   {
    121     UInt64 rating = GetCompressRating(dictionarySize, info.GlobalTime, info.GlobalFreq, info.UnpackSize);
    122     PrintResults(f, info, rating, EncodeRes);
    123   }
    124   return S_OK;
    125 }
    126 
    127 static const char *kSep = "  | ";
    128 
    129 
    130 HRESULT CBenchCallback::SetDecodeResult(const CBenchInfo &info, bool final)
    131 {
    132   if (NConsoleClose::TestBreakSignal())
    133     return E_ABORT;
    134   if (final)
    135   {
    136     UInt64 rating = GetDecompressRating(info.GlobalTime, info.GlobalFreq, info.UnpackSize, info.PackSize, info.NumIterations);
    137     fputs(kSep, f);
    138     CBenchInfo info2 = info;
    139     info2.UnpackSize *= info2.NumIterations;
    140     info2.PackSize *= info2.NumIterations;
    141     info2.NumIterations = 1;
    142     PrintResults(f, info2, rating, DecodeRes);
    143   }
    144   return S_OK;
    145 }
    146 
    147 static void PrintRequirements(FILE *f, const char *sizeString, UInt64 size, const char *threadsString, UInt32 numThreads)
    148 {
    149   fprintf(f, "\nRAM %s ", sizeString);
    150   PrintNumber(f, (size >> 20), 5);
    151   fprintf(f, " MB,  # %s %3d", threadsString, (unsigned int)numThreads);
    152 }
    153 
    154 HRESULT LzmaBenchCon(
    155   DECL_EXTERNAL_CODECS_LOC_VARS
    156   FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary)
    157 {
    158   if (!CrcInternalTest())
    159     return S_FALSE;
    160   #ifndef _7ZIP_ST
    161   UInt64 ramSize = NWindows::NSystem::GetRamSize();  //
    162   UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors();
    163   PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs);
    164   if (numThreads == (UInt32)-1)
    165     numThreads = numCPUs;
    166   if (numThreads > 1)
    167     numThreads &= ~1;
    168   if (dictionary == (UInt32)-1)
    169   {
    170     int dicSizeLog;
    171     for (dicSizeLog = 25; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--)
    172       if (GetBenchMemoryUsage(numThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize)
    173         break;
    174     dictionary = (1 << dicSizeLog);
    175   }
    176   #else
    177   if (dictionary == (UInt32)-1)
    178     dictionary = (1 << 22);
    179   numThreads = 1;
    180   #endif
    181 
    182   PrintRequirements(f, "usage:", GetBenchMemoryUsage(numThreads, dictionary), "Benchmark threads:   ", numThreads);
    183 
    184   CBenchCallback callback;
    185   callback.Init();
    186   callback.f = f;
    187 
    188   fprintf(f, "\n\nDict        Compressing          |        Decompressing\n   ");
    189   int j;
    190   for (j = 0; j < 2; j++)
    191   {
    192     fprintf(f, "   Speed Usage    R/U Rating");
    193     if (j == 0)
    194       fputs(kSep, f);
    195   }
    196   fprintf(f, "\n   ");
    197   for (j = 0; j < 2; j++)
    198   {
    199     fprintf(f, "    KB/s     %%   MIPS   MIPS");
    200     if (j == 0)
    201       fputs(kSep, f);
    202   }
    203   fprintf(f, "\n\n");
    204   for (UInt32 i = 0; i < numIterations; i++)
    205   {
    206     const int kStartDicLog = 22;
    207     int pow = (dictionary < ((UInt32)1 << kStartDicLog)) ? kBenchMinDicLogSize : kStartDicLog;
    208     while (((UInt32)1 << pow) > dictionary)
    209       pow--;
    210     for (; ((UInt32)1 << pow) <= dictionary; pow++)
    211     {
    212       fprintf(f, "%2d:", pow);
    213       callback.dictionarySize = (UInt32)1 << pow;
    214       HRESULT res = LzmaBench(
    215         EXTERNAL_CODECS_LOC_VARS
    216         numThreads, callback.dictionarySize, &callback);
    217       fprintf(f, "\n");
    218       RINOK(res);
    219     }
    220   }
    221   callback.Normalize();
    222   fprintf(f, "----------------------------------------------------------------\nAvr:");
    223   PrintTotals(f, callback.EncodeRes);
    224   fprintf(f, "     ");
    225   PrintTotals(f, callback.DecodeRes);
    226   fprintf(f, "\nTot:");
    227   CTotalBenchRes midRes;
    228   midRes.SetMid(callback.EncodeRes, callback.DecodeRes);
    229   PrintTotals(f, midRes);
    230   fprintf(f, "\n");
    231   return S_OK;
    232 }
    233 
    234 struct CTempValues
    235 {
    236   UInt64 *Values;
    237   CTempValues(UInt32 num) { Values = new UInt64[num]; }
    238   ~CTempValues() { delete []Values; }
    239 };
    240 
    241 HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary)
    242 {
    243   if (!CrcInternalTest())
    244     return S_FALSE;
    245 
    246   #ifndef _7ZIP_ST
    247   UInt64 ramSize = NWindows::NSystem::GetRamSize();
    248   UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors();
    249   PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs);
    250   if (numThreads == (UInt32)-1)
    251     numThreads = numCPUs;
    252   #else
    253   numThreads = 1;
    254   #endif
    255   if (dictionary == (UInt32)-1)
    256     dictionary = (1 << 24);
    257 
    258   CTempValues speedTotals(numThreads);
    259   fprintf(f, "\n\nSize");
    260   for (UInt32 ti = 0; ti < numThreads; ti++)
    261   {
    262     fprintf(f, " %5d", ti + 1);
    263     speedTotals.Values[ti] = 0;
    264   }
    265   fprintf(f, "\n\n");
    266 
    267   UInt64 numSteps = 0;
    268   for (UInt32 i = 0; i < numIterations; i++)
    269   {
    270     for (int pow = 10; pow < 32; pow++)
    271     {
    272       UInt32 bufSize = (UInt32)1 << pow;
    273       if (bufSize > dictionary)
    274         break;
    275       fprintf(f, "%2d: ", pow);
    276       UInt64 speed;
    277       for (UInt32 ti = 0; ti < numThreads; ti++)
    278       {
    279         if (NConsoleClose::TestBreakSignal())
    280           return E_ABORT;
    281         RINOK(CrcBench(ti + 1, bufSize, speed));
    282         PrintNumber(f, (speed >> 20), 5);
    283         speedTotals.Values[ti] += speed;
    284       }
    285       fprintf(f, "\n");
    286       numSteps++;
    287     }
    288   }
    289   if (numSteps != 0)
    290   {
    291     fprintf(f, "\nAvg:");
    292     for (UInt32 ti = 0; ti < numThreads; ti++)
    293       PrintNumber(f, ((speedTotals.Values[ti] / numSteps) >> 20), 5);
    294     fprintf(f, "\n");
    295   }
    296   return S_OK;
    297 }
    298