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