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;
InitCTotalBenchRes23 void Init() { NumIterations = 0; Rating = 0; Usage = 0; RPU = 0; }
NormalizeCTotalBenchRes24 void Normalize()
25 {
26 if (NumIterations == 0)
27 return;
28 Rating /= NumIterations;
29 Usage /= NumIterations;
30 RPU /= NumIterations;
31 NumIterations = 1;
32 }
SetMidCTotalBenchRes33 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;
InitCBenchCallback47 void Init() { EncodeRes.Init(); DecodeRes.Init(); }
NormalizeCBenchCallback48 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
NormalizeVals(UInt64 & v1,UInt64 & v2)54 static void NormalizeVals(UInt64 &v1, UInt64 &v2)
55 {
56 while (v1 > 1000000)
57 {
58 v1 >>= 1;
59 v2 >>= 1;
60 }
61 }
62
MyMultDiv64(UInt64 value,UInt64 elapsedTime,UInt64 freq)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
PrintNumber(FILE * f,UInt64 value,int size)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
PrintRating(FILE * f,UInt64 rating)82 static void PrintRating(FILE *f, UInt64 rating)
83 {
84 PrintNumber(f, rating / 1000000, 6);
85 }
86
PrintResults(FILE * f,UInt64 usage,UInt64 rpu,UInt64 rating)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
PrintResults(FILE * f,const CBenchInfo & info,UInt64 rating,CTotalBenchRes & res)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
PrintTotals(FILE * f,const CTotalBenchRes & res)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
SetEncodeResult(const CBenchInfo & info,bool final)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
SetDecodeResult(const CBenchInfo & info,bool final)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
PrintRequirements(FILE * f,const char * sizeString,UInt64 size,const char * threadsString,UInt32 numThreads)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
LzmaBenchCon(DECL_EXTERNAL_CODECS_LOC_VARS FILE * f,UInt32 numIterations,UInt32 numThreads,UInt32 dictionary)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;
CTempValuesCTempValues237 CTempValues(UInt32 num) { Values = new UInt64[num]; }
~CTempValuesCTempValues238 ~CTempValues() { delete []Values; }
239 };
240
CrcBenchCon(FILE * f,UInt32 numIterations,UInt32 numThreads,UInt32 dictionary)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