1 // BenchmarkDialog.cpp
2
3 #include "StdAfx.h"
4
5 #include "../../../../C/CpuArch.h"
6
7 #include "../../../Common/Defs.h"
8 #include "../../../Common/IntToString.h"
9 #include "../../../Common/MyException.h"
10 #include "../../../Common/StringConvert.h"
11 #include "../../../Common/StringToInt.h"
12
13 #include "../../../Windows/System.h"
14 #include "../../../Windows/Thread.h"
15
16 #include "../../Common/MethodProps.h"
17
18 #include "../FileManager/HelpUtils.h"
19
20 #include "../../MyVersion.h"
21
22 #include "BenchmarkDialog.h"
23
24 using namespace NWindows;
25
26 #define kHelpTopic "fm/benchmark.htm"
27
28 static const UINT_PTR kTimerID = 4;
29 static const UINT kTimerElapse = 1000;
30
31 #ifdef LANG
32 #include "../FileManager/LangUtils.h"
33 #endif
34
35 using namespace NWindows;
36
37 UString HResultToMessage(HRESULT errorCode);
38
39 #ifdef LANG
40 static const UInt32 kLangIDs[] =
41 {
42 IDT_BENCH_DICTIONARY,
43 IDT_BENCH_MEMORY,
44 IDT_BENCH_NUM_THREADS,
45 IDT_BENCH_SPEED,
46 IDT_BENCH_RATING_LABEL,
47 IDT_BENCH_USAGE_LABEL,
48 IDT_BENCH_RPU_LABEL,
49 IDG_BENCH_COMPRESSING,
50 IDG_BENCH_DECOMPRESSING,
51 IDG_BENCH_TOTAL_RATING,
52 IDT_BENCH_CURRENT,
53 IDT_BENCH_RESULTING,
54 IDT_BENCH_ELAPSED,
55 IDT_BENCH_PASSES,
56 IDB_STOP,
57 IDB_RESTART
58 };
59
60 static const UInt32 kLangIDs_Colon[] =
61 {
62 IDT_BENCH_SIZE
63 };
64
65 #endif
66
67 static LPCTSTR const kProcessingString = TEXT("...");
68 static LPCTSTR const kMB = TEXT(" MB");
69 static LPCTSTR const kMIPS = TEXT(" MIPS");
70 static LPCTSTR const kKBs = TEXT(" KB/s");
71
72 static const unsigned kMinDicLogSize =
73 #ifdef UNDER_CE
74 20;
75 #else
76 21;
77 #endif
78
79 static const UInt32 kMinDicSize = (1 << kMinDicLogSize);
80 static const UInt32 kMaxDicSize =
81 #ifdef MY_CPU_64BIT
82 (1 << 30);
83 #else
84 (1 << 27);
85 #endif
86
OnInit()87 bool CBenchmarkDialog::OnInit()
88 {
89 #ifdef LANG
90 LangSetWindowText(*this, IDD_BENCH);
91 LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
92 LangSetDlgItems_Colon(*this, kLangIDs_Colon, ARRAY_SIZE(kLangIDs_Colon));
93 LangSetDlgItemText(*this, IDT_BENCH_CURRENT2, IDT_BENCH_CURRENT);
94 LangSetDlgItemText(*this, IDT_BENCH_RESULTING2, IDT_BENCH_RESULTING);
95 #endif
96
97 Sync.Init();
98
99 if (TotalMode)
100 {
101 _consoleEdit.Attach(GetItem(IDE_BENCH2_EDIT));
102 LOGFONT f;
103 memset(&f, 0, sizeof(f));
104 f.lfHeight = 14;
105 f.lfWidth = 0;
106 f.lfWeight = FW_DONTCARE;
107 f.lfCharSet = DEFAULT_CHARSET;
108 f.lfOutPrecision = OUT_DEFAULT_PRECIS;
109 f.lfClipPrecision = CLIP_DEFAULT_PRECIS;
110 f.lfQuality = DEFAULT_QUALITY;
111
112 f.lfPitchAndFamily = FIXED_PITCH;
113 // MyStringCopy(f.lfFaceName, TEXT(""));
114 // f.lfFaceName[0] = 0;
115 _font.Create(&f);
116 if (_font._font)
117 _consoleEdit.SendMsg(WM_SETFONT, (WPARAM)_font._font, TRUE);
118 }
119
120 UInt32 numCPUs = 1;
121
122 {
123 UString s ("/ ");
124
125 NSystem::CProcessAffinity threadsInfo;
126 threadsInfo.InitST();
127
128 #ifndef _7ZIP_ST
129
130 if (threadsInfo.Get() && threadsInfo.processAffinityMask != 0)
131 numCPUs = threadsInfo.GetNumProcessThreads();
132 else
133 numCPUs = NSystem::GetNumberOfProcessors();
134
135 #endif
136
137 s.Add_UInt32(numCPUs);
138 s += GetProcessThreadsInfo(threadsInfo);
139 SetItemText(IDT_BENCH_HARDWARE_THREADS, s);
140 }
141
142 {
143 UString s;
144 {
145 AString s1, s2;
146 GetSysInfo(s1, s2);
147 s = s1;
148 SetItemText(IDT_BENCH_SYS1, s);
149 if (s1 != s2 && !s2.IsEmpty())
150 {
151 s = s2;
152 SetItemText(IDT_BENCH_SYS2, s);
153 }
154 }
155 /*
156 {
157 GetVersionString(s);
158 SetItemText(IDT_BENCH_SYSTEM, s);
159 }
160 */
161 {
162 AString s2;
163 GetCpuName(s2);
164 s = s2;
165 SetItemText(IDT_BENCH_CPU, s);
166 }
167 /*
168 {
169 AString s2;
170 GetCpuFeatures(s2);
171 s = s2;
172 SetItemText(IDT_BENCH_CPU_FEATURE, s);
173 }
174 */
175
176 s = "7-Zip " MY_VERSION_CPU;
177 SetItemText(IDT_BENCH_VER, s);
178 }
179
180
181 if (numCPUs < 1)
182 numCPUs = 1;
183 numCPUs = MyMin(numCPUs, (UInt32)(1 << 8));
184
185 if (Sync.NumThreads == (UInt32)(Int32)-1)
186 {
187 Sync.NumThreads = numCPUs;
188 if (Sync.NumThreads > 1)
189 Sync.NumThreads &= ~1;
190 }
191 m_NumThreads.Attach(GetItem(IDC_BENCH_NUM_THREADS));
192 int cur = 0;
193 for (UInt32 num = 1; num <= numCPUs * 2;)
194 {
195 TCHAR s[16];
196 ConvertUInt32ToString(num, s);
197 int index = (int)m_NumThreads.AddString(s);
198 m_NumThreads.SetItemData(index, num);
199 if (num <= Sync.NumThreads)
200 cur = index;
201 if (num > 1)
202 num++;
203 num++;
204 }
205 m_NumThreads.SetCurSel(cur);
206 Sync.NumThreads = GetNumberOfThreads();
207
208 m_Dictionary.Attach(GetItem(IDC_BENCH_DICTIONARY));
209 cur = 0;
210
211 ramSize = (UInt64)(sizeof(size_t)) << 29;
212 ramSize_Defined = NSystem::GetRamSize(ramSize);
213
214 #ifdef UNDER_CE
215 const UInt32 kNormalizedCeSize = (16 << 20);
216 if (ramSize > kNormalizedCeSize && ramSize < (33 << 20))
217 ramSize = kNormalizedCeSize;
218 #endif
219
220 if (Sync.DictionarySize == (UInt32)(Int32)-1)
221 {
222 unsigned dicSizeLog = 25;
223
224 #ifdef UNDER_CE
225 dicSizeLog = 20;
226 #endif
227
228 if (ramSize_Defined)
229 for (; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--)
230 if (GetBenchMemoryUsage(Sync.NumThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize)
231 break;
232 Sync.DictionarySize = (1 << dicSizeLog);
233 }
234
235 if (Sync.DictionarySize < kMinDicSize) Sync.DictionarySize = kMinDicSize;
236 if (Sync.DictionarySize > kMaxDicSize) Sync.DictionarySize = kMaxDicSize;
237
238 for (unsigned i = kMinDicLogSize; i <= 30; i++)
239 for (unsigned j = 0; j < 2; j++)
240 {
241 UInt32 dict = ((UInt32)1 << i) + ((UInt32)j << (i - 1));
242 if (dict > kMaxDicSize)
243 continue;
244 TCHAR s[32];
245 ConvertUInt32ToString((dict >> 20), s);
246 lstrcat(s, kMB);
247 int index = (int)m_Dictionary.AddString(s);
248 m_Dictionary.SetItemData(index, dict);
249 if (dict <= Sync.DictionarySize)
250 cur = index;
251 }
252 m_Dictionary.SetCurSel(cur);
253
254 OnChangeSettings();
255
256 Sync._startEvent.Set();
257 _timer = SetTimer(kTimerID, kTimerElapse);
258
259 if (TotalMode)
260 NormalizeSize(true);
261 else
262 NormalizePosition();
263 return CModalDialog::OnInit();
264 }
265
OnSize(WPARAM,int xSize,int ySize)266 bool CBenchmarkDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)
267 {
268 if (!TotalMode)
269 return false;
270 int mx, my;
271 GetMargins(8, mx, my);
272 int bx1, bx2, by;
273 GetItemSizes(IDCANCEL, bx1, by);
274 GetItemSizes(IDHELP, bx2, by);
275
276 {
277 int y = ySize - my - by;
278 int x = xSize - mx - bx1;
279
280 InvalidateRect(NULL);
281
282 MoveItem(IDCANCEL, x, y, bx1, by);
283 MoveItem(IDHELP, x - mx - bx2, y, bx2, by);
284 }
285
286 if (_consoleEdit)
287 {
288 int yPos = ySize - my - by;
289 RECT rect;
290 GetClientRectOfItem(IDE_BENCH2_EDIT, rect);
291 int y = rect.top;
292 int ySize2 = yPos - my - y;
293 const int kMinYSize = 20;
294 int xx = xSize - mx * 2;
295 if (ySize2 < kMinYSize)
296 {
297 ySize2 = kMinYSize;
298 }
299 _consoleEdit.Move(mx, y, xx, ySize2);
300 }
301 return false;
302 }
303
GetNumberOfThreads()304 UInt32 CBenchmarkDialog::GetNumberOfThreads()
305 {
306 return (UInt32)m_NumThreads.GetItemData_of_CurSel();
307 }
308
309
SetItemText_Number(int itemID,UInt64 val,LPCTSTR post)310 void CBenchmarkDialog::SetItemText_Number(int itemID, UInt64 val, LPCTSTR post)
311 {
312 TCHAR s[64];
313 ConvertUInt64ToString(val, s);
314 if (post)
315 lstrcat(s, post);
316 SetItemText(itemID, s);
317 }
318
PrintSize_MB(UString & s,UInt64 size)319 static void PrintSize_MB(UString &s, UInt64 size)
320 {
321 char temp[32];
322 ConvertUInt64ToString((size + (1 << 20) - 1) >> 20, temp);
323 s += temp;
324 s += kMB;
325 }
326
327 extern bool g_LargePagesMode;
328
OnChangeDictionary()329 UInt32 CBenchmarkDialog::OnChangeDictionary()
330 {
331 const UInt32 dict = (UInt32)m_Dictionary.GetItemData_of_CurSel();
332 const UInt64 memUsage = GetBenchMemoryUsage(GetNumberOfThreads(), dict);
333
334 UString s;
335 PrintSize_MB(s, memUsage);
336 if (ramSize_Defined)
337 {
338 s += " / ";
339 PrintSize_MB(s, ramSize);
340 }
341 if (g_LargePagesMode)
342 s += " LP";
343
344 SetItemText(IDT_BENCH_MEMORY_VAL, s);
345
346 return dict;
347 }
348
349 static const UInt32 g_IDs[] =
350 {
351 IDT_BENCH_COMPRESS_USAGE1,
352 IDT_BENCH_COMPRESS_USAGE2,
353 IDT_BENCH_COMPRESS_SPEED1,
354 IDT_BENCH_COMPRESS_SPEED2,
355 IDT_BENCH_COMPRESS_RATING1,
356 IDT_BENCH_COMPRESS_RATING2,
357 IDT_BENCH_COMPRESS_RPU1,
358 IDT_BENCH_COMPRESS_RPU2,
359
360 IDT_BENCH_DECOMPR_SPEED1,
361 IDT_BENCH_DECOMPR_SPEED2,
362 IDT_BENCH_DECOMPR_RATING1,
363 IDT_BENCH_DECOMPR_RATING2,
364 IDT_BENCH_DECOMPR_USAGE1,
365 IDT_BENCH_DECOMPR_USAGE2,
366 IDT_BENCH_DECOMPR_RPU1,
367 IDT_BENCH_DECOMPR_RPU2,
368
369 IDT_BENCH_TOTAL_USAGE_VAL,
370 IDT_BENCH_TOTAL_RATING_VAL,
371 IDT_BENCH_TOTAL_RPU_VAL
372
373 // IDT_BENCH_FREQ_CUR,
374 // IDT_BENCH_FREQ_RES
375 };
376
OnChangeSettings()377 void CBenchmarkDialog::OnChangeSettings()
378 {
379 EnableItem(IDB_STOP, true);
380 UInt32 dict = OnChangeDictionary();
381
382 for (int i = 0; i < ARRAY_SIZE(g_IDs); i++)
383 SetItemText(g_IDs[i], kProcessingString);
384 _startTime = GetTickCount();
385 PrintTime();
386 NWindows::NSynchronization::CCriticalSectionLock lock(Sync.CS);
387 Sync.Init();
388 Sync.DictionarySize = dict;
389 Sync.Changed = true;
390 Sync.NumThreads = GetNumberOfThreads();
391 }
392
OnRestartButton()393 void CBenchmarkDialog::OnRestartButton()
394 {
395 OnChangeSettings();
396 }
397
OnStopButton()398 void CBenchmarkDialog::OnStopButton()
399 {
400 EnableItem(IDB_STOP, false);
401 Sync.Pause();
402 }
403
OnHelp()404 void CBenchmarkDialog::OnHelp()
405 {
406 ShowHelpWindow(kHelpTopic);
407 }
408
OnCancel()409 void CBenchmarkDialog::OnCancel()
410 {
411 Sync.Stop();
412 KillTimer(_timer);
413 CModalDialog::OnCancel();
414 }
415
416 void GetTimeString(UInt64 timeValue, wchar_t *s);
417
PrintTime()418 void CBenchmarkDialog::PrintTime()
419 {
420 UInt32 curTime = ::GetTickCount();
421 UInt32 elapsedTime = (curTime - _startTime);
422 UInt32 elapsedSec = elapsedTime / 1000;
423 if (elapsedSec != 0 && Sync.WasPaused())
424 return;
425 WCHAR s[40];
426 GetTimeString(elapsedSec, s);
427 SetItemText(IDT_BENCH_ELAPSED_VAL, s);
428 }
429
PrintRating(UInt64 rating,UINT controlID)430 void CBenchmarkDialog::PrintRating(UInt64 rating, UINT controlID)
431 {
432 SetItemText_Number(controlID, rating / 1000000, kMIPS);
433 }
434
PrintUsage(UInt64 usage,UINT controlID)435 void CBenchmarkDialog::PrintUsage(UInt64 usage, UINT controlID)
436 {
437 SetItemText_Number(controlID, (usage + 5000) / 10000, TEXT("%"));
438 }
439
PrintResults(UInt32 dictionarySize,const CBenchInfo2 & info,UINT usageID,UINT speedID,UINT rpuID,UINT ratingID,bool decompressMode)440 void CBenchmarkDialog::PrintResults(
441 UInt32 dictionarySize,
442 const CBenchInfo2 &info,
443 UINT usageID, UINT speedID, UINT rpuID, UINT ratingID,
444 bool decompressMode)
445 {
446 if (info.GlobalTime == 0)
447 return;
448
449 {
450 const UInt64 speed = info.UnpackSize * info.NumIterations * info.GlobalFreq / info.GlobalTime;
451 SetItemText_Number(speedID, speed >> 10, kKBs);
452 }
453 UInt64 rating;
454 if (decompressMode)
455 rating = info.GetDecompressRating();
456 else
457 rating = info.GetCompressRating(dictionarySize);
458
459 PrintRating(rating, ratingID);
460 PrintRating(info.GetRatingPerUsage(rating), rpuID);
461 PrintUsage(info.GetUsage(), usageID);
462 }
463
OnTimer(WPARAM,LPARAM)464 bool CBenchmarkDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */)
465 {
466 bool printTime = true;
467 if (TotalMode)
468 {
469 if (Sync.WasStopped())
470 printTime = false;
471 }
472 if (printTime)
473 PrintTime();
474
475 if (TotalMode)
476 {
477 bool wasChanged = false;
478 {
479 NWindows::NSynchronization::CCriticalSectionLock lock(Sync.CS);
480
481 if (Sync.TextWasChanged)
482 {
483 wasChanged = true;
484 Bench2Text += Sync.Text;
485 Sync.Text.Empty();
486 Sync.TextWasChanged = false;
487 }
488 }
489 if (wasChanged)
490 _consoleEdit.SetText(Bench2Text);
491 return true;
492 }
493
494 SetItemText_Number(IDT_BENCH_SIZE_VAL, (Sync.ProcessedSize >> 20), kMB);
495
496 SetItemText_Number(IDT_BENCH_PASSES_VAL, Sync.NumPasses);
497
498 /*
499 if (Sync.FirstPath)
500 SetItemText_Number(IDT_BENCH_FREQ_CUR, Sync.Freq, TEXT(" MHz"));
501 else
502 SetItemText_Number(IDT_BENCH_FREQ_RES, Sync.Freq, TEXT(" MHz"));
503 */
504
505 /*
506 if (Sync.FreqWasChanged)
507 {
508 SetItemText(IDT_BENCH_FREQ, Sync.Freq);
509 Sync.FreqWasChanged = false;
510 }
511 */
512
513 {
514 UInt32 dicSizeTemp = (UInt32)MyMax(Sync.ProcessedSize, UInt64(1) << 20);
515 dicSizeTemp = MyMin(dicSizeTemp, Sync.DictionarySize),
516 PrintResults(dicSizeTemp,
517 Sync.CompressingInfoTemp,
518 IDT_BENCH_COMPRESS_USAGE1,
519 IDT_BENCH_COMPRESS_SPEED1,
520 IDT_BENCH_COMPRESS_RPU1,
521 IDT_BENCH_COMPRESS_RATING1);
522 }
523
524 {
525 PrintResults(
526 Sync.DictionarySize,
527 Sync.CompressingInfo,
528 IDT_BENCH_COMPRESS_USAGE2,
529 IDT_BENCH_COMPRESS_SPEED2,
530 IDT_BENCH_COMPRESS_RPU2,
531 IDT_BENCH_COMPRESS_RATING2);
532 }
533
534 {
535 PrintResults(
536 Sync.DictionarySize,
537 Sync.DecompressingInfoTemp,
538 IDT_BENCH_DECOMPR_USAGE1,
539 IDT_BENCH_DECOMPR_SPEED1,
540 IDT_BENCH_DECOMPR_RPU1,
541 IDT_BENCH_DECOMPR_RATING1,
542 true);
543 }
544 {
545 PrintResults(
546 Sync.DictionarySize,
547 Sync.DecompressingInfo,
548 IDT_BENCH_DECOMPR_USAGE2,
549 IDT_BENCH_DECOMPR_SPEED2,
550 IDT_BENCH_DECOMPR_RPU2,
551 IDT_BENCH_DECOMPR_RATING2,
552 true);
553 if (Sync.DecompressingInfo.GlobalTime > 0 &&
554 Sync.CompressingInfo.GlobalTime > 0)
555 {
556 UInt64 comprRating = Sync.CompressingInfo.GetCompressRating(Sync.DictionarySize);
557 UInt64 decomprRating = Sync.DecompressingInfo.GetDecompressRating();
558 PrintRating((comprRating + decomprRating) / 2, IDT_BENCH_TOTAL_RATING_VAL);
559 PrintRating((
560 Sync.CompressingInfo.GetRatingPerUsage(comprRating) +
561 Sync.DecompressingInfo.GetRatingPerUsage(decomprRating)) / 2, IDT_BENCH_TOTAL_RPU_VAL);
562 PrintUsage(
563 (Sync.CompressingInfo.GetUsage() +
564 Sync.DecompressingInfo.GetUsage()) / 2, IDT_BENCH_TOTAL_USAGE_VAL);
565 }
566 }
567 return true;
568 }
569
OnCommand(int code,int itemID,LPARAM lParam)570 bool CBenchmarkDialog::OnCommand(int code, int itemID, LPARAM lParam)
571 {
572 if (code == CBN_SELCHANGE &&
573 (itemID == IDC_BENCH_DICTIONARY ||
574 itemID == IDC_BENCH_NUM_THREADS))
575 {
576 OnChangeSettings();
577 return true;
578 }
579 return CModalDialog::OnCommand(code, itemID, lParam);
580 }
581
OnButtonClicked(int buttonID,HWND buttonHWND)582 bool CBenchmarkDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
583 {
584 switch (buttonID)
585 {
586 case IDB_RESTART:
587 OnRestartButton();
588 return true;
589 case IDB_STOP:
590 OnStopButton();
591 return true;
592 }
593 return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
594 }
595
596 struct CThreadBenchmark
597 {
598 CBenchmarkDialog *BenchmarkDialog;
599 DECL_EXTERNAL_CODECS_LOC_VARS2;
600 // UInt32 dictionarySize;
601 // UInt32 numThreads;
602
603 HRESULT Process();
604 HRESULT Result;
MyThreadFunctionCThreadBenchmark605 static THREAD_FUNC_DECL MyThreadFunction(void *param)
606 {
607 ((CThreadBenchmark *)param)->Result = ((CThreadBenchmark *)param)->Process();
608 return 0;
609 }
610 };
611
612 struct CBenchCallback: public IBenchCallback
613 {
614 UInt32 dictionarySize;
615 CBenchProgressSync *Sync;
616
617 // void AddCpuFreq(UInt64 cpuFreq);
618 HRESULT SetFreq(bool showFreq, UInt64 cpuFreq);
619 HRESULT SetEncodeResult(const CBenchInfo &info, bool final);
620 HRESULT SetDecodeResult(const CBenchInfo &info, bool final);
621 };
622
623 /*
624 void CBenchCallback::AddCpuFreq(UInt64 cpuFreq)
625 {
626 NSynchronization::CCriticalSectionLock lock(Sync->CS);
627 {
628 wchar_t s[32];
629 ConvertUInt64ToString(cpuFreq, s);
630 Sync->Freq.Add_Space_if_NotEmpty();
631 Sync->Freq += s;
632 Sync->FreqWasChanged = true;
633 }
634 }
635 */
636
SetFreq(bool,UInt64)637 HRESULT CBenchCallback::SetFreq(bool /* showFreq */, UInt64 /* cpuFreq */)
638 {
639 return S_OK;
640 }
641
SetEncodeResult(const CBenchInfo & info,bool final)642 HRESULT CBenchCallback::SetEncodeResult(const CBenchInfo &info, bool final)
643 {
644 NSynchronization::CCriticalSectionLock lock(Sync->CS);
645 if (Sync->Changed || Sync->Paused || Sync->Stopped)
646 return E_ABORT;
647 Sync->ProcessedSize = info.UnpackSize * info.NumIterations;
648 if (final && Sync->CompressingInfo.GlobalTime == 0)
649 {
650 (CBenchInfo&)Sync->CompressingInfo = info;
651 if (Sync->CompressingInfo.GlobalTime == 0)
652 Sync->CompressingInfo.GlobalTime = 1;
653 }
654 else
655 (CBenchInfo&)Sync->CompressingInfoTemp = info;
656
657 return S_OK;
658 }
659
SetDecodeResult(const CBenchInfo & info,bool final)660 HRESULT CBenchCallback::SetDecodeResult(const CBenchInfo &info, bool final)
661 {
662 NSynchronization::CCriticalSectionLock lock(Sync->CS);
663 if (Sync->Changed || Sync->Paused || Sync->Stopped)
664 return E_ABORT;
665 CBenchInfo info2 = info;
666 if (final && Sync->DecompressingInfo.GlobalTime == 0)
667 {
668 (CBenchInfo&)Sync->DecompressingInfo = info2;
669 if (Sync->DecompressingInfo.GlobalTime == 0)
670 Sync->DecompressingInfo.GlobalTime = 1;
671 }
672 else
673 (CBenchInfo&)Sync->DecompressingInfoTemp = info2;
674 return S_OK;
675 }
676
677 struct CBenchCallback2: public IBenchPrintCallback
678 {
679 CBenchProgressSync *Sync;
680 bool TotalMode;
681
682 void Print(const char *s);
683 void NewLine();
684 HRESULT CheckBreak();
685 };
686
Print(const char * s)687 void CBenchCallback2::Print(const char *s)
688 {
689 if (TotalMode)
690 {
691 NSynchronization::CCriticalSectionLock lock(Sync->CS);
692 Sync->Text += s;
693 Sync->TextWasChanged = true;
694 }
695 }
696
NewLine()697 void CBenchCallback2::NewLine()
698 {
699 Print("\xD\n");
700 }
701
CheckBreak()702 HRESULT CBenchCallback2::CheckBreak()
703 {
704 if (Sync->Changed || Sync->Paused || Sync->Stopped)
705 return E_ABORT;
706 return S_OK;
707 }
708
709
710
711 /*
712 struct CFreqCallback: public IBenchFreqCallback
713 {
714 CBenchProgressSync *Sync;
715
716 virtual void AddCpuFreq(UInt64 freq);
717 };
718
719 void CFreqCallback::AddCpuFreq(UInt64 freq)
720 {
721 NSynchronization::CCriticalSectionLock lock(Sync->CS);
722 Sync->Freq = freq;
723 }
724 */
725
726
727
Process()728 HRESULT CThreadBenchmark::Process()
729 {
730 CBenchProgressSync &sync = BenchmarkDialog->Sync;
731 sync.WaitCreating();
732 try
733 {
734 for (;;)
735 {
736 if (sync.WasStopped())
737 return 0;
738 if (sync.WasPaused())
739 {
740 Sleep(200);
741 continue;
742 }
743 UInt32 dictionarySize;
744 UInt32 numThreads;
745 {
746 NSynchronization::CCriticalSectionLock lock(sync.CS);
747 if (sync.Stopped || sync.Paused)
748 continue;
749 if (sync.Changed)
750 sync.Init();
751 dictionarySize = sync.DictionarySize;
752 numThreads = sync.NumThreads;
753 /*
754 if (sync.CompressingInfo.GlobalTime != 0)
755 sync.FirstPath = false;
756 */
757 }
758
759 CBenchCallback callback;
760 callback.dictionarySize = dictionarySize;
761 callback.Sync = &sync;
762 CBenchCallback2 callback2;
763 callback2.TotalMode = BenchmarkDialog->TotalMode;
764 callback2.Sync = &sync;
765 // CFreqCallback freqCallback;
766 // freqCallback.Sync = &sync;
767 HRESULT result;
768
769 try
770 {
771 CObjectVector<CProperty> props;
772 if (BenchmarkDialog->TotalMode)
773 {
774 props = BenchmarkDialog->Props;
775 }
776 else
777 {
778 {
779 CProperty prop;
780 prop.Name = "mt";
781 prop.Value.Add_UInt32(numThreads);
782 props.Add(prop);
783 }
784 {
785 CProperty prop;
786 prop.Name = 'd';
787 prop.Name.Add_UInt32(dictionarySize);
788 prop.Name += 'b';
789 props.Add(prop);
790 }
791 }
792
793 result = Bench(EXTERNAL_CODECS_LOC_VARS
794 BenchmarkDialog->TotalMode ? &callback2 : NULL,
795 BenchmarkDialog->TotalMode ? NULL : &callback,
796 // &freqCallback,
797 props, 1, false);
798
799 if (BenchmarkDialog->TotalMode)
800 {
801 sync.Stop();
802 }
803 }
804 catch(...)
805 {
806 result = E_FAIL;
807 }
808
809 if (result != S_OK)
810 {
811 if (result != E_ABORT)
812 {
813 {
814 NSynchronization::CCriticalSectionLock lock(sync.CS);
815 sync.Pause();
816 }
817 UString message;
818 if (result == S_FALSE)
819 message = "Decoding error";
820 else if (result == CLASS_E_CLASSNOTAVAILABLE)
821 message = "Can't find 7z.dll";
822 else
823 message = HResultToMessage(result);
824 BenchmarkDialog->MessageBoxError(message);
825 }
826 }
827 else
828 {
829 NSynchronization::CCriticalSectionLock lock(sync.CS);
830 sync.NumPasses++;
831 }
832 }
833 // return S_OK;
834 }
835 catch(CSystemException &e)
836 {
837 BenchmarkDialog->MessageBoxError(HResultToMessage(e.ErrorCode));
838 return E_FAIL;
839 }
840 catch(...)
841 {
842 BenchmarkDialog->MessageBoxError(HResultToMessage(E_FAIL));
843 return E_FAIL;
844 }
845 }
846
ParseNumberString(const UString & s,NCOM::CPropVariant & prop)847 static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop)
848 {
849 const wchar_t *end;
850 UInt64 result = ConvertStringToUInt64(s, &end);
851 if (*end != 0 || s.IsEmpty())
852 prop = s;
853 else if (result <= (UInt32)0xFFFFFFFF)
854 prop = (UInt32)result;
855 else
856 prop = result;
857 }
858
Benchmark(DECL_EXTERNAL_CODECS_LOC_VARS const CObjectVector<CProperty> & props,HWND hwndParent)859 HRESULT Benchmark(
860 DECL_EXTERNAL_CODECS_LOC_VARS
861 const CObjectVector<CProperty> &props, HWND hwndParent)
862 {
863 CThreadBenchmark benchmarker;
864 #ifdef EXTERNAL_CODECS
865 benchmarker.__externalCodecs = __externalCodecs;
866 #endif
867
868 CBenchmarkDialog bd;
869 bd.Props = props;
870 bd.TotalMode = false;
871 bd.Sync.DictionarySize = (UInt32)(Int32)-1;
872 bd.Sync.NumThreads = (UInt32)(Int32)-1;
873
874 COneMethodInfo method;
875
876 UInt32 numCPUs = 1;
877 #ifndef _7ZIP_ST
878 numCPUs = NSystem::GetNumberOfProcessors();
879 #endif
880 UInt32 numThreads = numCPUs;
881
882 FOR_VECTOR (i, props)
883 {
884 const CProperty &prop = props[i];
885 UString name = prop.Name;
886 name.MakeLower_Ascii();
887 if (name.IsEqualTo_Ascii_NoCase("m") && prop.Value == L"*")
888 {
889 bd.TotalMode = true;
890 continue;
891 }
892
893 NCOM::CPropVariant propVariant;
894 if (!prop.Value.IsEmpty())
895 ParseNumberString(prop.Value, propVariant);
896 if (name.IsPrefixedBy(L"mt"))
897 {
898 #ifndef _7ZIP_ST
899 RINOK(ParseMtProp(name.Ptr(2), propVariant, numCPUs, numThreads));
900 if (numThreads != numCPUs)
901 bd.Sync.NumThreads = numThreads;
902 #endif
903 continue;
904 }
905 if (name.IsEqualTo("testtime"))
906 {
907 // UInt32 testTime = 4;
908 // RINOK(ParsePropToUInt32(L"", propVariant, testTime));
909 continue;
910 }
911 RINOK(method.ParseMethodFromPROPVARIANT(name, propVariant));
912 }
913
914 if (bd.TotalMode)
915 {
916 // bd.Bench2Text.Empty();
917 bd.Bench2Text = "7-Zip " MY_VERSION_CPU;
918 bd.Bench2Text += (char)0xD;
919 bd.Bench2Text.Add_LF();
920 }
921
922 {
923 UInt32 dict;
924 if (method.Get_DicSize(dict))
925 bd.Sync.DictionarySize = dict;
926 }
927
928 benchmarker.BenchmarkDialog = &bd;
929
930 NWindows::CThread thread;
931 RINOK(thread.Create(CThreadBenchmark::MyThreadFunction, &benchmarker));
932 bd.Create(hwndParent);
933 return thread.Wait();
934 }
935