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