LzmaBenchCon.cpp 7.8 KB

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