Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'CPP/7zip/UI/GUI/BenchmarkDialog.cpp')
-rw-r--r--CPP/7zip/UI/GUI/BenchmarkDialog.cpp1688
1 files changed, 1337 insertions, 351 deletions
diff --git a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp
index 94dfab4c..44d25035 100644
--- a/CPP/7zip/UI/GUI/BenchmarkDialog.cpp
+++ b/CPP/7zip/UI/GUI/BenchmarkDialog.cpp
@@ -10,15 +10,27 @@
#include "../../../Common/StringConvert.h"
#include "../../../Common/StringToInt.h"
+#include "../../../Windows/Synchronization.h"
#include "../../../Windows/System.h"
#include "../../../Windows/Thread.h"
+#include "../../../Windows/SystemInfo.h"
+
+#include "../../../Windows/Control/ComboBox.h"
+#include "../../../Windows/Control/Edit.h"
#include "../../Common/MethodProps.h"
+#include "../FileManager/DialogSize.h"
#include "../FileManager/HelpUtils.h"
+#ifdef LANG
+#include "../FileManager/LangUtils.h"
+#endif
#include "../../MyVersion.h"
+#include "../Common/Bench.h"
+
+#include "BenchmarkDialogRes.h"
#include "BenchmarkDialog.h"
using namespace NWindows;
@@ -26,13 +38,350 @@ using namespace NWindows;
#define kHelpTopic "fm/benchmark.htm"
static const UINT_PTR kTimerID = 4;
-static const UINT kTimerElapse = 1000;
+static const UINT kTimerElapse = 1000; // 1000
+
+// use PRINT_ITER_TIME to show time of each iteration in log box
+// #define PRINT_ITER_TIME
+
+static const unsigned kRatingVector_NumBundlesMax = 20;
+
+enum MyBenchMessages
+{
+ k_Message_Finished = WM_APP + 1
+};
+
+enum My_Message_WPARAM
+{
+ k_Msg_WPARM_Thread_Finished = 0,
+ k_Msg_WPARM_Iter_Finished,
+ k_Msg_WPARM_Enc1_Finished
+};
+
+
+struct CBenchPassResult
+{
+ CTotalBenchRes Enc;
+ CTotalBenchRes Dec;
+ #ifdef PRINT_ITER_TIME
+ DWORD Ticks;
+ #endif
+ // CBenchInfo EncInfo; // for debug
+ // CBenchPassResult() {};
+};
+
+
+struct CTotalBenchRes2: public CTotalBenchRes
+{
+ UInt64 UnpackSize;
+
+ void Init()
+ {
+ CTotalBenchRes::Init();
+ UnpackSize = 0;
+ }
+
+ void SetFrom_BenchInfo(const CBenchInfo &info)
+ {
+ NumIterations2 = 1;
+ Generate_From_BenchInfo(info);
+ UnpackSize = info.Get_UnpackSize_Full();
+ }
+
+ void Update_With_Res2(const CTotalBenchRes2 &r)
+ {
+ Update_With_Res(r);
+ UnpackSize += r.UnpackSize;
+ }
+};
+
+
+struct CSyncData
+{
+ UInt32 NumPasses_Finished;
+
+ // UInt64 NumEncProgress; // for debug
+ // UInt64 NumDecProgress; // for debug
+ // CBenchInfo EncInfo; // for debug
+
+ CTotalBenchRes2 Enc_BenchRes_1;
+ CTotalBenchRes2 Enc_BenchRes;
+
+ CTotalBenchRes2 Dec_BenchRes_1;
+ CTotalBenchRes2 Dec_BenchRes;
+
+ #ifdef PRINT_ITER_TIME
+ DWORD TotalTicks;
+ #endif
+
+ int RatingVector_DeletedIndex;
+ // UInt64 RatingVector_NumDeleted;
+
+ bool BenchWasFinished; // all passes were finished
+ bool NeedPrint_Freq;
+ bool NeedPrint_RatingVector;
+ bool NeedPrint_Enc_1;
+ bool NeedPrint_Enc;
+ bool NeedPrint_Dec_1;
+ bool NeedPrint_Dec;
+ bool NeedPrint_Tot; // intermediate Total was updated after current pass
+
+ void Init();
+};
+
+
+void CSyncData::Init()
+{
+ NumPasses_Finished = 0;
+
+ // NumEncProgress = 0;
+ // NumDecProgress = 0;
+
+ Enc_BenchRes.Init();
+ Enc_BenchRes_1.Init();
+ Dec_BenchRes.Init();
+ Dec_BenchRes_1.Init();
+
+ #ifdef PRINT_ITER_TIME
+ TotalTicks = 0;
+ #endif
+
+ RatingVector_DeletedIndex = -1;
+ // RatingVector_NumDeleted = 0;
+
+ BenchWasFinished =
+ NeedPrint_Freq =
+ NeedPrint_RatingVector =
+ NeedPrint_Enc_1 =
+ NeedPrint_Enc =
+ NeedPrint_Dec_1 =
+ NeedPrint_Dec =
+ NeedPrint_Tot = false;
+};
+
+
+struct CBenchProgressSync
+{
+ bool Exit; // GUI asks BenchThread to Exit, and BenchThread reads that variable
+ UInt32 NumThreads;
+ UInt64 DictSize;
+ UInt32 NumPasses_Limit;
+ int Level;
+
+ // must be written by benchmark thread, read by GUI thread */
+ CSyncData sd;
+ CRecordVector<CBenchPassResult> RatingVector;
+
+ NWindows::NSynchronization::CCriticalSection CS;
+
+ AString Text;
+ bool TextWasChanged;
+
+ /* BenchFinish_Task_HRESULT - for result from benchmark code
+ BenchFinish_Thread_HRESULT - for Exceptions and service errors
+ these arreos must be shown even if user escapes benchmark */
+
+ HRESULT BenchFinish_Task_HRESULT;
+ HRESULT BenchFinish_Thread_HRESULT;
+
+ UInt32 NumFreqThreadsPrev;
+ UString FreqString_Sync;
+ UString FreqString_GUI;
+
+ CBenchProgressSync()
+ {
+ NumPasses_Limit = 1;
+ }
+
+ void Init();
+
+ void SendExit()
+ {
+ NWindows::NSynchronization::CCriticalSectionLock lock(CS);
+ Exit = true;
+ }
+};
+
+
+void CBenchProgressSync::Init()
+{
+ Exit = false;
+
+ BenchFinish_Task_HRESULT = S_OK;
+ BenchFinish_Thread_HRESULT = S_OK;
+
+ sd.Init();
+ RatingVector.Clear();
+
+ NumFreqThreadsPrev = 0;
+ FreqString_Sync.Empty();
+ FreqString_GUI.Empty();
+
+ Text.Empty();
+ TextWasChanged = true;
+}
+
+
+
+struct CMyFont
+{
+ HFONT _font;
+ CMyFont(): _font(NULL) {}
+ ~CMyFont()
+ {
+ if (_font)
+ DeleteObject(_font);
+ }
+ void Create(const LOGFONT *lplf)
+ {
+ _font = CreateFontIndirect(lplf);
+ }
+};
+
+
+class CBenchmarkDialog;
+
+struct CThreadBenchmark
+{
+ CBenchmarkDialog *BenchmarkDialog;
+ DECL_EXTERNAL_CODECS_LOC_VARS2;
+ // HRESULT Result;
+
+ HRESULT Process();
+ static THREAD_FUNC_DECL MyThreadFunction(void *param)
+ {
+ /* ((CThreadBenchmark *)param)->Result = */
+ ((CThreadBenchmark *)param)->Process();
+ return 0;
+ }
+};
+
+
+class CBenchmarkDialog:
+ public NWindows::NControl::CModalDialog
+{
+ NWindows::NControl::CComboBox m_Dictionary;
+ NWindows::NControl::CComboBox m_NumThreads;
+ NWindows::NControl::CComboBox m_NumPasses;
+ NWindows::NControl::CEdit _consoleEdit;
+ UINT_PTR _timer;
+
+ UInt32 _startTime;
+ UInt32 _finishTime;
+ bool _finishTime_WasSet;
+
+ bool WasStopped_in_GUI;
+ bool ExitWasAsked_in_GUI;
+ bool NeedRestart;
+
+ CMyFont _font;
+
+ UInt64 RamSize;
+ UInt64 RamSize_Limit;
+ bool RamSize_Defined;
+
+ UInt32 NumPasses_Finished_Prev;
+
+ UString ElapsedSec_Prev;
+
+ void InitSyncNew()
+ {
+ NumPasses_Finished_Prev = (UInt32)(Int32)-1;
+ ElapsedSec_Prev.Empty();
+ Sync.Init();
+ }
+
+ virtual bool OnInit();
+ virtual bool OnDestroy();
+ virtual bool OnSize(WPARAM /* wParam */, int xSize, int ySize);
+ virtual bool OnMessage(UINT message, WPARAM wParam, LPARAM lParam);
+ virtual bool OnCommand(int code, int itemID, LPARAM lParam);
+ virtual void OnHelp();
+ virtual void OnCancel();
+ virtual bool OnTimer(WPARAM timerID, LPARAM callback);
+ virtual bool OnButtonClicked(int buttonID, HWND buttonHWND);
+
+ void Disable_Stop_Button();
+ void OnStopButton();
+ void RestartBenchmark();
+ void StartBenchmark();
+
+ void UpdateGui();
+
+ void PrintTime();
+ void PrintRating(UInt64 rating, UINT controlID);
+ void PrintUsage(UInt64 usage, UINT controlID);
+ void PrintBenchRes(const CTotalBenchRes2 &info, const UINT ids[]);
+
+ UInt32 GetNumberOfThreads();
+ size_t OnChangeDictionary();
+
+ void SetItemText_Number(int itemID, UInt64 val, LPCTSTR post = NULL);
+ void Print_MemUsage(UString &s, UInt64 memUsage) const;
+ bool IsMemoryUsageOK(UInt64 memUsage) const
+ { return memUsage + (1 << 20) <= RamSize_Limit; }
+
+ void MyKillTimer();
+
+ void SendExit_Status(const wchar_t *message)
+ {
+ SetItemText(IDT_BENCH_ERROR_MESSAGE, message);
+ Sync.SendExit();
+ }
+
+public:
+ CBenchProgressSync Sync;
+
+ bool TotalMode;
+ CObjectVector<CProperty> Props;
+
+ CSysString Bench2Text;
+
+ NWindows::CThread _thread;
+ CThreadBenchmark _threadBenchmark;
+
+ CBenchmarkDialog():
+ _timer(0),
+ TotalMode(false),
+ WasStopped_in_GUI(false),
+ ExitWasAsked_in_GUI(false),
+ NeedRestart(false)
+ {}
+
+ ~CBenchmarkDialog();
+
+ bool PostMsg_Finish(LPARAM param)
+ {
+ if ((HWND)*this)
+ return PostMsg(k_Message_Finished, param);
+ // the (HWND)*this is NULL only for some internal code failure
+ return true;
+ }
+
+ INT_PTR Create(HWND wndParent = 0)
+ {
+ BIG_DIALOG_SIZE(332, 228);
+ return CModalDialog::Create(TotalMode ? IDD_BENCH_TOTAL : SIZED_DIALOG(IDD_BENCH), wndParent);
+ }
+ void MessageBoxError(LPCWSTR message)
+ {
+ MessageBoxW(*this, message, L"7-Zip", MB_ICONERROR);
+ }
+ void MessageBoxError_Status(LPCWSTR message)
+ {
+ UString s ("ERROR: ");
+ s += message;
+ MessageBoxError(s);
+ SetItemText(IDT_BENCH_ERROR_MESSAGE, s);
+ }
+};
+
+
+
+
+
+
-#ifdef LANG
-#include "../FileManager/LangUtils.h"
-#endif
-using namespace NWindows;
UString HResultToMessage(HRESULT errorCode);
@@ -65,36 +414,48 @@ static const UInt32 kLangIDs_Colon[] =
#endif
static LPCTSTR const kProcessingString = TEXT("...");
+static LPCTSTR const kGB = TEXT(" GB");
static LPCTSTR const kMB = TEXT(" MB");
-static LPCTSTR const kMIPS = TEXT(" MIPS");
+static LPCTSTR const kKB = TEXT(" KB");
+// static LPCTSTR const kMIPS = TEXT(" MIPS");
static LPCTSTR const kKBs = TEXT(" KB/s");
-static const unsigned kMinDicLogSize =
- #ifdef UNDER_CE
- 20;
- #else
- 21;
- #endif
+static const unsigned kMinDicLogSize = 18;
-static const UInt32 kMinDicSize = (1 << kMinDicLogSize);
-static const UInt32 kMaxDicSize =
+static const UInt32 kMinDicSize = (UInt32)1 << kMinDicLogSize;
+static const size_t kMaxDicSize = (size_t)1 << (22 + sizeof(size_t) / 4 * 5);
+// static const size_t kMaxDicSize = (size_t)1 << 16;
+ /*
#ifdef MY_CPU_64BIT
- (1 << 30);
+ (UInt32)(Int32)-1; // we can use it, if we want 4 GB buffer
+ // (UInt32)15 << 28;
#else
- (1 << 27);
+ (UInt32)1 << 27;
#endif
+ */
+
+
+static int ComboBox_Add_UInt32(NWindows::NControl::CComboBox &cb, UInt32 v)
+{
+ TCHAR s[16];
+ ConvertUInt32ToString(v, s);
+ int index = (int)cb.AddString(s);
+ cb.SetItemData(index, v);
+ return index;
+}
+
bool CBenchmarkDialog::OnInit()
{
#ifdef LANG
LangSetWindowText(*this, IDD_BENCH);
LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
- LangSetDlgItems_Colon(*this, kLangIDs_Colon, ARRAY_SIZE(kLangIDs_Colon));
+ // LangSetDlgItems_Colon(*this, kLangIDs_Colon, ARRAY_SIZE(kLangIDs_Colon));
LangSetDlgItemText(*this, IDT_BENCH_CURRENT2, IDT_BENCH_CURRENT);
LangSetDlgItemText(*this, IDT_BENCH_RESULTING2, IDT_BENCH_RESULTING);
#endif
- Sync.Init();
+ InitSyncNew();
if (TotalMode)
{
@@ -120,154 +481,194 @@ bool CBenchmarkDialog::OnInit()
UInt32 numCPUs = 1;
{
- UString s ("/ ");
+ AString s ("/ ");
NSystem::CProcessAffinity threadsInfo;
threadsInfo.InitST();
#ifndef _7ZIP_ST
-
if (threadsInfo.Get() && threadsInfo.processAffinityMask != 0)
numCPUs = threadsInfo.GetNumProcessThreads();
else
numCPUs = NSystem::GetNumberOfProcessors();
-
#endif
s.Add_UInt32(numCPUs);
s += GetProcessThreadsInfo(threadsInfo);
- SetItemText(IDT_BENCH_HARDWARE_THREADS, s);
- }
-
- {
- UString s;
- {
- AString s1, s2;
- GetSysInfo(s1, s2);
- s = s1;
- SetItemText(IDT_BENCH_SYS1, s);
- if (s1 != s2 && !s2.IsEmpty())
- {
- s = s2;
- SetItemText(IDT_BENCH_SYS2, s);
- }
- }
- /*
+ SetItemTextA(IDT_BENCH_HARDWARE_THREADS, s);
+
{
- GetVersionString(s);
- SetItemText(IDT_BENCH_SYSTEM, s);
+ AString s2;
+ GetSysInfo(s, s2);
+ SetItemTextA(IDT_BENCH_SYS1, s);
+ if (s != s2 && !s2.IsEmpty())
+ SetItemTextA(IDT_BENCH_SYS2, s2);
}
- */
{
- AString s2;
- GetCpuName(s2);
- s = s2;
- SetItemText(IDT_BENCH_CPU, s);
+ GetCpuName_MultiLine(s);
+ SetItemTextA(IDT_BENCH_CPU, s);
}
{
- AString s2;
- AddCpuFeatures(s2);
- s = s2;
- SetItemText(IDT_BENCH_CPU_FEATURE, s);
+ GetOsInfoText(s);
+ s += " : ";
+ AddCpuFeatures(s);
+ SetItemTextA(IDT_BENCH_CPU_FEATURE, s);
}
s = "7-Zip " MY_VERSION_CPU;
- SetItemText(IDT_BENCH_VER, s);
+ SetItemTextA(IDT_BENCH_VER, s);
}
+ // ----- Num Threads ----------
+
if (numCPUs < 1)
numCPUs = 1;
- numCPUs = MyMin(numCPUs, (UInt32)(1 << 8));
+ numCPUs = MyMin(numCPUs, (UInt32)(1 << 6)); // it's WIN32 limit
+
+ UInt32 numThreads = Sync.NumThreads;
+
+ if (numThreads == (UInt32)(Int32)-1)
+ numThreads = numCPUs;
+ if (numThreads > 1)
+ numThreads &= ~1;
+ const UInt32 kNumThreadsMax = (1 << 12);
+ if (numThreads > kNumThreadsMax)
+ numThreads = kNumThreadsMax;
- if (Sync.NumThreads == (UInt32)(Int32)-1)
- {
- Sync.NumThreads = numCPUs;
- if (Sync.NumThreads > 1)
- Sync.NumThreads &= ~1;
- }
m_NumThreads.Attach(GetItem(IDC_BENCH_NUM_THREADS));
+ const UInt32 numTheads_Combo = numCPUs * 2;
+ UInt32 v = 1;
int cur = 0;
- for (UInt32 num = 1; num <= numCPUs * 2;)
+ for (; v <= numTheads_Combo;)
{
- TCHAR s[16];
- ConvertUInt32ToString(num, s);
- int index = (int)m_NumThreads.AddString(s);
- m_NumThreads.SetItemData(index, num);
- if (num <= Sync.NumThreads)
+ int index = ComboBox_Add_UInt32(m_NumThreads, v);
+ const UInt32 vNext = v + (v < 2 ? 1 : 2);
+ if (v <= numThreads)
+ if (numThreads < vNext || vNext > numTheads_Combo)
+ {
+ if (v != numThreads)
+ index = ComboBox_Add_UInt32(m_NumThreads, numThreads);
cur = index;
- if (num > 1)
- num++;
- num++;
+ }
+ v = vNext;
}
m_NumThreads.SetCurSel(cur);
Sync.NumThreads = GetNumberOfThreads();
+
+ // ----- Dictionary ----------
+
m_Dictionary.Attach(GetItem(IDC_BENCH_DICTIONARY));
- cur = 0;
- ramSize = (UInt64)(sizeof(size_t)) << 29;
- ramSize_Defined = NSystem::GetRamSize(ramSize);
+ RamSize = (UInt64)(sizeof(size_t)) << 29;
+ RamSize_Defined = NSystem::GetRamSize(RamSize);
+
#ifdef UNDER_CE
const UInt32 kNormalizedCeSize = (16 << 20);
- if (ramSize > kNormalizedCeSize && ramSize < (33 << 20))
- ramSize = kNormalizedCeSize;
+ if (RamSize > kNormalizedCeSize && RamSize < (33 << 20))
+ RamSize = kNormalizedCeSize;
#endif
+ RamSize_Limit = RamSize / 16 * 15;
- if (Sync.DictionarySize == (UInt32)(Int32)-1)
+ if (Sync.DictSize == (UInt64)(Int64)-1)
{
unsigned dicSizeLog = 25;
-
#ifdef UNDER_CE
dicSizeLog = 20;
#endif
-
- if (ramSize_Defined)
+ if (RamSize_Defined)
for (; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--)
- if (GetBenchMemoryUsage(Sync.NumThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize)
+ if (IsMemoryUsageOK(GetBenchMemoryUsage(
+ Sync.NumThreads, Sync.Level, (UInt64)1 << dicSizeLog, TotalMode)))
break;
- Sync.DictionarySize = (1 << dicSizeLog);
+ Sync.DictSize = (UInt64)1 << dicSizeLog;
}
- if (Sync.DictionarySize < kMinDicSize) Sync.DictionarySize = kMinDicSize;
- if (Sync.DictionarySize > kMaxDicSize) Sync.DictionarySize = kMaxDicSize;
+ if (Sync.DictSize < kMinDicSize) Sync.DictSize = kMinDicSize;
+ if (Sync.DictSize > kMaxDicSize) Sync.DictSize = kMaxDicSize;
- for (unsigned i = kMinDicLogSize; i <= 30; i++)
- for (unsigned j = 0; j < 2; j++)
- {
- UInt32 dict = ((UInt32)1 << i) + ((UInt32)j << (i - 1));
- if (dict > kMaxDicSize)
- continue;
+ cur = 0;
+ for (unsigned i = (kMinDicLogSize - 1) * 2; i <= (32 - 1) * 2; i++)
+ {
+ const size_t dict = (size_t)(2 + (i & 1)) << (i / 2);
+ // if (i == (32 - 1) * 2) dict = kMaxDicSize;
TCHAR s[32];
- ConvertUInt32ToString((dict >> 20), s);
- lstrcat(s, kMB);
- int index = (int)m_Dictionary.AddString(s);
+ const TCHAR *post;
+ UInt32 d;
+ if (dict >= ((UInt32)1 << 31)) { d = (UInt32)(dict >> 30); post = kGB; }
+ else if (dict >= ((UInt32)1 << 21)) { d = (UInt32)(dict >> 20); post = kMB; }
+ else { d = (UInt32)(dict >> 10); post = kKB; }
+ ConvertUInt32ToString(d, s);
+ lstrcat(s, post);
+ const int index = (int)m_Dictionary.AddString(s);
m_Dictionary.SetItemData(index, dict);
- if (dict <= Sync.DictionarySize)
+ if (dict <= Sync.DictSize)
cur = index;
+ if (dict >= kMaxDicSize)
+ break;
}
m_Dictionary.SetCurSel(cur);
- OnChangeSettings();
- Sync._startEvent.Set();
- _timer = SetTimer(kTimerID, kTimerElapse);
+ // ----- Num Passes ----------
+
+ m_NumPasses.Attach(GetItem(IDC_BENCH_NUM_PASSES));
+ cur = 0;
+ v = 1;
+ for (;;)
+ {
+ int index = ComboBox_Add_UInt32(m_NumPasses, v);
+ const bool isLast = (v >= 10000000);
+ UInt32 vNext = v * 10;
+ if (v < 2) vNext = 2;
+ else if (v < 5) vNext = 5;
+ else if (v < 10) vNext = 10;
+
+ if (v <= Sync.NumPasses_Limit)
+ if (isLast || Sync.NumPasses_Limit < vNext)
+ {
+ if (v != Sync.NumPasses_Limit)
+ index = ComboBox_Add_UInt32(m_NumPasses, Sync.NumPasses_Limit);
+ cur = index;
+ }
+ v = vNext;
+ if (isLast)
+ break;
+ }
+ m_NumPasses.SetCurSel(cur);
if (TotalMode)
NormalizeSize(true);
else
NormalizePosition();
+
+ RestartBenchmark();
+
return CModalDialog::OnInit();
}
+
bool CBenchmarkDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)
{
- if (!TotalMode)
- return false;
int mx, my;
GetMargins(8, mx, my);
+
+ if (!TotalMode)
+ {
+ RECT rect;
+ GetClientRectOfItem(IDT_BENCH_LOG, rect);
+ int x = xSize - rect.left - mx;
+ int y = ySize - rect.top - my;
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ MoveItem(IDT_BENCH_LOG, rect.left, rect.top, x, y, true);
+ return false;
+ }
+
int bx1, bx2, by;
+
GetItemSizes(IDCANCEL, bx1, by);
GetItemSizes(IDHELP, bx2, by);
@@ -299,12 +700,28 @@ bool CBenchmarkDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)
return false;
}
+
UInt32 CBenchmarkDialog::GetNumberOfThreads()
{
return (UInt32)m_NumThreads.GetItemData_of_CurSel();
}
+#define UINT_TO_STR_3(s, val) { \
+ s[0] = (wchar_t)('0' + (val) / 100); \
+ s[1] = (wchar_t)('0' + (val) % 100 / 10); \
+ s[2] = (wchar_t)('0' + (val) % 10); \
+ s[3] = 0; }
+
+static void NumberToDot3(UInt64 val, WCHAR *s)
+{
+ ConvertUInt64ToString(val / 1000, s);
+ const UInt32 rem = (UInt32)(val % 1000);
+ s += MyStringLen(s);
+ *s++ = '.';
+ UINT_TO_STR_3(s, rem);
+}
+
void CBenchmarkDialog::SetItemText_Number(int itemID, UInt64 val, LPCTSTR post)
{
TCHAR s[64];
@@ -314,33 +731,42 @@ void CBenchmarkDialog::SetItemText_Number(int itemID, UInt64 val, LPCTSTR post)
SetItemText(itemID, s);
}
-static void PrintSize_MB(UString &s, UInt64 size)
+static void AddSize_MB(UString &s, UInt64 size)
{
- char temp[32];
- ConvertUInt64ToString((size + (1 << 20) - 1) >> 20, temp);
- s += temp;
+ s.Add_UInt64((size + (1 << 20) - 1) >> 20);
s += kMB;
}
-
-UInt32 CBenchmarkDialog::OnChangeDictionary()
+void CBenchmarkDialog::Print_MemUsage(UString &s, UInt64 memUsage) const
{
- const UInt32 dict = (UInt32)m_Dictionary.GetItemData_of_CurSel();
- const UInt64 memUsage = GetBenchMemoryUsage(GetNumberOfThreads(), dict);
-
- UString s;
- PrintSize_MB(s, memUsage);
- if (ramSize_Defined)
+ AddSize_MB(s, memUsage);
+ if (RamSize_Defined)
{
s += " / ";
- PrintSize_MB(s, ramSize);
+ AddSize_MB(s, RamSize);
}
+}
+
+size_t CBenchmarkDialog::OnChangeDictionary()
+{
+ const size_t dict = (size_t)m_Dictionary.GetItemData_of_CurSel();
+ const UInt64 memUsage = GetBenchMemoryUsage(GetNumberOfThreads(),
+ Sync.Level,
+ dict,
+ false); // totalBench mode
+
+ UString s;
+ Print_MemUsage(s, memUsage);
#ifdef _7ZIP_LARGE_PAGES
{
AString s2;
Add_LargePages_String(s2);
- s += s2;
+ if (!s2.IsEmpty())
+ {
+ s.Add_Space();
+ s += s2;
+ }
}
#endif
@@ -349,8 +775,11 @@ UInt32 CBenchmarkDialog::OnChangeDictionary()
return dict;
}
+
static const UInt32 g_IDs[] =
{
+ IDT_BENCH_COMPRESS_SIZE1,
+ IDT_BENCH_COMPRESS_SIZE2,
IDT_BENCH_COMPRESS_USAGE1,
IDT_BENCH_COMPRESS_USAGE2,
IDT_BENCH_COMPRESS_SPEED1,
@@ -360,6 +789,8 @@ static const UInt32 g_IDs[] =
IDT_BENCH_COMPRESS_RPU1,
IDT_BENCH_COMPRESS_RPU2,
+ IDT_BENCH_DECOMPR_SIZE1,
+ IDT_BENCH_DECOMPR_SIZE2,
IDT_BENCH_DECOMPR_SPEED1,
IDT_BENCH_DECOMPR_SPEED2,
IDT_BENCH_DECOMPR_RATING1,
@@ -372,108 +803,456 @@ static const UInt32 g_IDs[] =
IDT_BENCH_TOTAL_USAGE_VAL,
IDT_BENCH_TOTAL_RATING_VAL,
IDT_BENCH_TOTAL_RPU_VAL
-
- // IDT_BENCH_FREQ_CUR,
- // IDT_BENCH_FREQ_RES
};
-void CBenchmarkDialog::OnChangeSettings()
+
+static const unsigned k_Ids_Enc_1[] = {
+ IDT_BENCH_COMPRESS_USAGE1,
+ IDT_BENCH_COMPRESS_SPEED1,
+ IDT_BENCH_COMPRESS_RPU1,
+ IDT_BENCH_COMPRESS_RATING1,
+ IDT_BENCH_COMPRESS_SIZE1 };
+
+static const unsigned k_Ids_Enc[] = {
+ IDT_BENCH_COMPRESS_USAGE2,
+ IDT_BENCH_COMPRESS_SPEED2,
+ IDT_BENCH_COMPRESS_RPU2,
+ IDT_BENCH_COMPRESS_RATING2,
+ IDT_BENCH_COMPRESS_SIZE2 };
+
+static const unsigned k_Ids_Dec_1[] = {
+ IDT_BENCH_DECOMPR_USAGE1,
+ IDT_BENCH_DECOMPR_SPEED1,
+ IDT_BENCH_DECOMPR_RPU1,
+ IDT_BENCH_DECOMPR_RATING1,
+ IDT_BENCH_DECOMPR_SIZE1 };
+
+static const unsigned k_Ids_Dec[] = {
+ IDT_BENCH_DECOMPR_USAGE2,
+ IDT_BENCH_DECOMPR_SPEED2,
+ IDT_BENCH_DECOMPR_RPU2,
+ IDT_BENCH_DECOMPR_RATING2,
+ IDT_BENCH_DECOMPR_SIZE2 };
+
+static const unsigned k_Ids_Tot[] = {
+ IDT_BENCH_TOTAL_USAGE_VAL,
+ 0,
+ IDT_BENCH_TOTAL_RPU_VAL,
+ IDT_BENCH_TOTAL_RATING_VAL,
+ 0 };
+
+
+void CBenchmarkDialog::MyKillTimer()
{
- EnableItem(IDB_STOP, true);
- UInt32 dict = OnChangeDictionary();
+ if (_timer != 0)
+ {
+ KillTimer(kTimerID);
+ _timer = 0;
+ }
+}
+
+
+bool CBenchmarkDialog::OnDestroy()
+{
+ /* actually timer was removed before.
+ also the timer must be removed by Windows, when window will be removed. */
+ MyKillTimer(); // it's optional code
+ return false; // we return (false) to perform default dialog operation
+}
+
+void SetErrorMessage_MemUsage(UString &s, UInt64 reqSize, UInt64 ramSize, UInt64 ramLimit, const UString &usageString);
+
+void CBenchmarkDialog::StartBenchmark()
+{
+ NeedRestart = false;
+ WasStopped_in_GUI = false;
+
+ SetItemText_Empty(IDT_BENCH_ERROR_MESSAGE);
+ MyKillTimer(); // optional code. timer was killed before
+
+ const size_t dict = OnChangeDictionary();
+ const UInt32 numThreads = GetNumberOfThreads();
+ const UInt32 numPasses = (UInt32)m_NumPasses.GetItemData_of_CurSel();
+
for (unsigned i = 0; i < ARRAY_SIZE(g_IDs); i++)
SetItemText(g_IDs[i], kProcessingString);
+
+ SetItemText_Empty(IDT_BENCH_LOG);
+ SetItemText_Empty(IDT_BENCH_ELAPSED_VAL);
+ SetItemText_Empty(IDT_BENCH_ERROR_MESSAGE);
+
+ const UInt64 memUsage = GetBenchMemoryUsage(numThreads, Sync.Level, dict,
+ false); // totalBench
+ if (!IsMemoryUsageOK(memUsage))
+ {
+ UString s2 = LangString(IDT_BENCH_MEMORY);
+ if (s2.IsEmpty())
+ GetItemText(IDT_BENCH_MEMORY, s2);
+ UString s;
+ SetErrorMessage_MemUsage(s, memUsage, RamSize, RamSize_Limit, s2);
+ MessageBoxError_Status(s);
+ return;
+ }
+
+ EnableItem(IDB_STOP, true);
+
_startTime = GetTickCount();
+ _finishTime = _startTime;
+ _finishTime_WasSet = false;
+
+ {
+ NWindows::NSynchronization::CCriticalSectionLock lock(Sync.CS);
+ InitSyncNew();
+ Sync.DictSize = dict;
+ Sync.NumThreads = numThreads;
+ Sync.NumPasses_Limit = numPasses;
+ }
+
PrintTime();
- NWindows::NSynchronization::CCriticalSectionLock lock(Sync.CS);
- Sync.Init();
- Sync.DictionarySize = dict;
- Sync.Changed = true;
- Sync.NumThreads = GetNumberOfThreads();
+
+ _timer = SetTimer(kTimerID, kTimerElapse);
+ if (_thread.Create(CThreadBenchmark::MyThreadFunction, &_threadBenchmark) != 0)
+ {
+ MyKillTimer();
+ MessageBoxError_Status(L"Can't create thread");
+ };
+ return;
}
-void CBenchmarkDialog::OnRestartButton()
+
+void CBenchmarkDialog::RestartBenchmark()
{
- OnChangeSettings();
+ if (ExitWasAsked_in_GUI)
+ return;
+
+ if (_thread.IsCreated())
+ {
+ NeedRestart = true;
+ SendExit_Status(L"Stop for restart ...");
+ }
+ else
+ StartBenchmark();
}
-void CBenchmarkDialog::OnStopButton()
+
+void CBenchmarkDialog::Disable_Stop_Button()
{
+ // if we disable focused button, then focus will be lost
+ if (GetFocus() == GetItem(IDB_STOP))
+ {
+ // SendMsg_NextDlgCtl_Prev();
+ SendMsg_NextDlgCtl_CtlId(IDB_RESTART);
+ }
EnableItem(IDB_STOP, false);
- Sync.Pause();
}
-void CBenchmarkDialog::OnHelp()
+
+void CBenchmarkDialog::OnStopButton()
{
- ShowHelpWindow(kHelpTopic);
+ if (ExitWasAsked_in_GUI)
+ return;
+
+ Disable_Stop_Button();
+
+ WasStopped_in_GUI = true;
+ if (_thread.IsCreated())
+ {
+ SendExit_Status(L"Stop ...");
+ }
}
+
+
void CBenchmarkDialog::OnCancel()
{
- Sync.Stop();
- KillTimer(_timer);
- CModalDialog::OnCancel();
+ ExitWasAsked_in_GUI = true;
+
+ /*
+ SendMsg_NextDlgCtl_Prev();
+ EnableItem(IDCANCEL, false);
+ */
+
+ if (_thread.IsCreated())
+ SendExit_Status(L"Cancel ...");
+ else
+ CModalDialog::OnCancel();
}
-void GetTimeString(UInt64 timeValue, wchar_t *s);
+
+void CBenchmarkDialog::OnHelp()
+{
+ ShowHelpWindow(kHelpTopic);
+}
+
+
+
+// void GetTimeString(UInt64 timeValue, wchar_t *s);
void CBenchmarkDialog::PrintTime()
{
- UInt32 curTime = ::GetTickCount();
- UInt32 elapsedTime = (curTime - _startTime);
- UInt32 elapsedSec = elapsedTime / 1000;
- if (elapsedSec != 0 && Sync.WasPaused())
+ const UInt32 curTime =
+ _finishTime_WasSet ?
+ _finishTime :
+ ::GetTickCount();
+
+ const UInt32 elapsedTime = (curTime - _startTime);
+
+ WCHAR s[64];
+
+ // GetTimeString(elapsedTime / 1000, s);
+ ConvertUInt32ToString(elapsedTime / 1000, s);
+
+ if (_finishTime_WasSet)
+ {
+ WCHAR *p = s + MyStringLen(s);
+ *p++ = '.';
+ UINT_TO_STR_3(p, elapsedTime % 1000);
+ }
+
+ // NumberToDot3((UInt64)elapsedTime, s);
+
+ wcscat(s, L" s");
+
+ // if (WasStopped_in_GUI) wcscat(s, L" X"); // for debug
+
+ if (s == ElapsedSec_Prev)
return;
- WCHAR s[40];
- GetTimeString(elapsedSec, s);
+
+ ElapsedSec_Prev = s;
+
+ // static cnt = 0; cnt++; wcscat(s, L" ");
+ // UString s2; s2.Add_UInt32(cnt); wcscat(s, s2.Ptr());
+
SetItemText(IDT_BENCH_ELAPSED_VAL, s);
}
+
+static UInt64 GetMips(UInt64 ips)
+{
+ return (ips + 500000) / 1000000;
+}
+
+
+static UInt64 GetUsagePercents(UInt64 usage)
+{
+ return Benchmark_GetUsage_Percents(usage);
+}
+
+
+static UInt32 GetRating(const CTotalBenchRes &info)
+{
+ UInt64 numIter = info.NumIterations2;
+ if (numIter == 0)
+ numIter = 1000000;
+ const UInt64 rating64 = GetMips(info.Rating / numIter);
+ // return rating64;
+ UInt32 rating32 = (UInt32)rating64;
+ if (rating32 != rating64)
+ rating32 = (UInt32)(Int32)-1;
+ return rating32;
+};
+
+
+static void AddUsageString(UString &s, const CTotalBenchRes &info)
+{
+ UInt64 numIter = info.NumIterations2;
+ if (numIter == 0)
+ numIter = 1000000;
+ UInt64 usage = GetUsagePercents(info.Usage / numIter);
+
+ wchar_t w[64];
+ ConvertUInt64ToString(usage, w);
+ unsigned len = MyStringLen(w);
+ while (len < 5)
+ {
+ s.Add_Space();
+ len++;
+ }
+ s += w;
+ s += "%";
+}
+
+
+static void Add_Dot3String(UString &s, UInt64 val)
+{
+ WCHAR temp[32];
+ NumberToDot3(val, temp);
+ s += temp;
+}
+
+
+static void AddRatingString(UString &s, const CTotalBenchRes &info)
+{
+ // AddUsageString(s, info);
+ // s += " ";
+ // s.Add_UInt32(GetRating(info));
+ Add_Dot3String(s, GetRating(info));
+};
+
+
+static void AddRatingsLine(UString &s, const CTotalBenchRes &enc, const CTotalBenchRes &dec
+ #ifdef PRINT_ITER_TIME
+ , DWORD ticks
+ #endif
+ )
+{
+ // AddUsageString(s, enc); s += " ";
+
+ AddRatingString(s, enc);
+ s += " ";
+ AddRatingString(s, dec);
+
+ CTotalBenchRes tot_BenchRes;
+ tot_BenchRes.SetSum(enc, dec);
+
+ s += " ";
+ AddRatingString(s, tot_BenchRes);
+
+ s += " "; AddUsageString(s, tot_BenchRes);
+
+
+ #ifdef PRINT_ITER_TIME
+ s += " ";
+ {
+ Add_Dot3String(s, ticks;
+ s += " s";
+ // s.Add_UInt32(ticks); s += " ms";
+ }
+ #endif
+}
+
+
void CBenchmarkDialog::PrintRating(UInt64 rating, UINT controlID)
{
- SetItemText_Number(controlID, rating / 1000000, kMIPS);
+ // SetItemText_Number(controlID, GetMips(rating), kMIPS);
+ WCHAR s[64];
+ NumberToDot3(GetMips(rating), s);
+ MyStringCat(s, L" GIPS");
+ SetItemText(controlID, s);
}
void CBenchmarkDialog::PrintUsage(UInt64 usage, UINT controlID)
{
- SetItemText_Number(controlID, (usage + 5000) / 10000, TEXT("%"));
+ SetItemText_Number(controlID, GetUsagePercents(usage), TEXT("%"));
}
-void CBenchmarkDialog::PrintResults(
- UInt32 dictionarySize,
- const CBenchInfo2 &info,
- UINT usageID, UINT speedID, UINT rpuID, UINT ratingID,
- bool decompressMode)
+
+// void SetItemText_Number
+
+void CBenchmarkDialog::PrintBenchRes(
+ const CTotalBenchRes2 &info,
+ const UINT ids[])
{
- if (info.GlobalTime == 0)
+ if (info.NumIterations2 == 0)
return;
-
+ if (ids[1] != 0)
+ SetItemText_Number(ids[1], (info.Speed >> 10) / info.NumIterations2, kKBs);
+ PrintRating(info.Rating / info.NumIterations2, ids[3]);
+ PrintRating(info.RPU / info.NumIterations2, ids[2]);
+ PrintUsage(info.Usage / info.NumIterations2, ids[0]);
+ if (ids[4] != 0)
{
- const UInt64 speed = info.UnpackSize * info.NumIterations * info.GlobalFreq / info.GlobalTime;
- SetItemText_Number(speedID, speed >> 10, kKBs);
+ UInt64 val = info.UnpackSize;
+ LPCTSTR kPostfix;
+ if (val >= ((UInt64)1 << 40))
+ {
+ kPostfix = kGB;
+ val >>= 30;
+ }
+ else
+ {
+ kPostfix = kMB;
+ val >>= 20;
+ }
+ SetItemText_Number(ids[4], val, kPostfix);
}
- UInt64 rating;
- if (decompressMode)
- rating = info.GetDecompressRating();
- else
- rating = info.GetCompressRating(dictionarySize);
-
- PrintRating(rating, ratingID);
- PrintRating(info.GetRatingPerUsage(rating), rpuID);
- PrintUsage(info.GetUsage(), usageID);
}
-bool CBenchmarkDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */)
+
+// static UInt32 k_Message_Finished_cnt = 0;
+// static UInt32 k_OnTimer_cnt = 0;
+
+bool CBenchmarkDialog::OnMessage(UINT message, WPARAM wParam, LPARAM lParam)
{
- bool printTime = true;
- if (TotalMode)
+ if (message != k_Message_Finished)
+ return CModalDialog::OnMessage(message, wParam, lParam);
+
{
- if (Sync.WasStopped())
- printTime = false;
+ if (wParam == k_Msg_WPARM_Thread_Finished)
+ {
+ _finishTime = GetTickCount();
+ _finishTime_WasSet = true;
+ MyKillTimer();
+
+ if (_thread.Wait_Close() != 0)
+ {
+ MessageBoxError_Status(L"Thread Wait Error");
+ }
+
+ if (!WasStopped_in_GUI)
+ {
+ WasStopped_in_GUI = true;
+ Disable_Stop_Button();
+ }
+
+ HRESULT res = Sync.BenchFinish_Thread_HRESULT;
+ if (res != S_OK)
+ // if (!ExitWasAsked_in_GUI || res != E_ABORT)
+ MessageBoxError_Status(HResultToMessage(res));
+
+ if (ExitWasAsked_in_GUI)
+ {
+ // SetItemText(IDT_BENCH_ERROR_MESSAGE, "before CModalDialog::OnCancel()");
+ // Sleep (2000);
+ // MessageBoxError(L"test");
+ CModalDialog::OnCancel();
+ return true;
+ }
+
+ SetItemText_Empty(IDT_BENCH_ERROR_MESSAGE);
+
+ res = Sync.BenchFinish_Task_HRESULT;
+ if (res != S_OK)
+ {
+ if (!WasStopped_in_GUI || res != E_ABORT)
+ {
+ UString m;
+ if (res == S_FALSE)
+ m = "Decoding error";
+ else if (res == CLASS_E_CLASSNOTAVAILABLE)
+ m = "Can't find 7z.dll";
+ else
+ m = HResultToMessage(res);
+ MessageBoxError_Status(m);
+ }
+ }
+
+ if (NeedRestart)
+ {
+ StartBenchmark();
+ return true;
+ }
+ }
+ // k_Message_Finished_cnt++;
+ UpdateGui();
+ return true;
}
- if (printTime)
- PrintTime();
+}
+
+
+bool CBenchmarkDialog::OnTimer(WPARAM timerID, LPARAM /* callback */)
+{
+ // k_OnTimer_cnt++;
+ if (timerID == kTimerID)
+ UpdateGui();
+ return true;
+}
+
+
+void CBenchmarkDialog::UpdateGui()
+{
+ PrintTime();
if (TotalMode)
{
@@ -491,103 +1270,147 @@ bool CBenchmarkDialog::OnTimer(WPARAM /* timerID */, LPARAM /* callback */)
}
if (wasChanged)
_consoleEdit.SetText(Bench2Text);
- return true;
+ return;
}
- SetItemText_Number(IDT_BENCH_SIZE_VAL, (Sync.ProcessedSize >> 20), kMB);
+ CSyncData sd;
+ CRecordVector<CBenchPassResult> RatingVector;
- SetItemText_Number(IDT_BENCH_PASSES_VAL, Sync.NumPasses);
+ {
+ NWindows::NSynchronization::CCriticalSectionLock lock(Sync.CS);
+ sd = Sync.sd;
- /*
- if (Sync.FirstPath)
- SetItemText_Number(IDT_BENCH_FREQ_CUR, Sync.Freq, TEXT(" MHz"));
- else
- SetItemText_Number(IDT_BENCH_FREQ_RES, Sync.Freq, TEXT(" MHz"));
- */
+ if (sd.NeedPrint_RatingVector)
+ RatingVector = Sync.RatingVector;
+
+ if (sd.NeedPrint_Freq)
+ {
+ Sync.FreqString_GUI = Sync.FreqString_Sync;
+ sd.NeedPrint_RatingVector = true;
+ }
- /*
- if (Sync.FreqWasChanged)
- {
- SetItemText(IDT_BENCH_FREQ, Sync.Freq);
- Sync.FreqWasChanged = false;
+ Sync.sd.NeedPrint_RatingVector = false;
+ Sync.sd.NeedPrint_Enc_1 = false;
+ Sync.sd.NeedPrint_Enc = false;
+ Sync.sd.NeedPrint_Dec_1 = false;
+ Sync.sd.NeedPrint_Dec = false;
+ Sync.sd.NeedPrint_Tot = false;
+ Sync.sd.NeedPrint_Freq = false;
}
- */
+ if (sd.NumPasses_Finished != NumPasses_Finished_Prev)
{
- UInt32 dicSizeTemp = (UInt32)MyMax(Sync.ProcessedSize, UInt64(1) << 20);
- dicSizeTemp = MyMin(dicSizeTemp, Sync.DictionarySize);
- PrintResults(dicSizeTemp,
- Sync.CompressingInfoTemp,
- IDT_BENCH_COMPRESS_USAGE1,
- IDT_BENCH_COMPRESS_SPEED1,
- IDT_BENCH_COMPRESS_RPU1,
- IDT_BENCH_COMPRESS_RATING1);
+ SetItemText_Number(IDT_BENCH_PASSES_VAL, sd.NumPasses_Finished, TEXT(" /"));
+ NumPasses_Finished_Prev = sd.NumPasses_Finished;
}
+ if (sd.NeedPrint_Enc_1) PrintBenchRes(sd.Enc_BenchRes_1, k_Ids_Enc_1);
+ if (sd.NeedPrint_Enc) PrintBenchRes(sd.Enc_BenchRes, k_Ids_Enc);
+ if (sd.NeedPrint_Dec_1) PrintBenchRes(sd.Dec_BenchRes_1, k_Ids_Dec_1);
+ if (sd.NeedPrint_Dec) PrintBenchRes(sd.Dec_BenchRes, k_Ids_Dec);
+
+ if (sd.BenchWasFinished && sd.NeedPrint_Tot)
{
- PrintResults(
- Sync.DictionarySize,
- Sync.CompressingInfo,
- IDT_BENCH_COMPRESS_USAGE2,
- IDT_BENCH_COMPRESS_SPEED2,
- IDT_BENCH_COMPRESS_RPU2,
- IDT_BENCH_COMPRESS_RATING2);
+ CTotalBenchRes2 tot_BenchRes = sd.Enc_BenchRes;
+ tot_BenchRes.Update_With_Res2(sd.Dec_BenchRes);
+ PrintBenchRes(tot_BenchRes, k_Ids_Tot);
}
+
+ if (sd.NeedPrint_RatingVector)
+ // for (unsigned k = 0; k < 1; k++)
{
- PrintResults(
- Sync.DictionarySize,
- Sync.DecompressingInfoTemp,
- IDT_BENCH_DECOMPR_USAGE1,
- IDT_BENCH_DECOMPR_SPEED1,
- IDT_BENCH_DECOMPR_RPU1,
- IDT_BENCH_DECOMPR_RATING1,
- true);
- }
- {
- PrintResults(
- Sync.DictionarySize,
- Sync.DecompressingInfo,
- IDT_BENCH_DECOMPR_USAGE2,
- IDT_BENCH_DECOMPR_SPEED2,
- IDT_BENCH_DECOMPR_RPU2,
- IDT_BENCH_DECOMPR_RATING2,
- true);
- if (Sync.DecompressingInfo.GlobalTime > 0 &&
- Sync.CompressingInfo.GlobalTime > 0)
+ UString s;
+ s += Sync.FreqString_GUI;
+ if (!RatingVector.IsEmpty())
{
- UInt64 comprRating = Sync.CompressingInfo.GetCompressRating(Sync.DictionarySize);
- UInt64 decomprRating = Sync.DecompressingInfo.GetDecompressRating();
- PrintRating((comprRating + decomprRating) / 2, IDT_BENCH_TOTAL_RATING_VAL);
- PrintRating((
- Sync.CompressingInfo.GetRatingPerUsage(comprRating) +
- Sync.DecompressingInfo.GetRatingPerUsage(decomprRating)) / 2, IDT_BENCH_TOTAL_RPU_VAL);
- PrintUsage(
- (Sync.CompressingInfo.GetUsage() +
- Sync.DecompressingInfo.GetUsage()) / 2, IDT_BENCH_TOTAL_USAGE_VAL);
+ if (!s.IsEmpty())
+ s.Add_LF();
+ s += "Compr Decompr Total CPU"
+ #ifdef PRINT_ITER_TIME
+ " Time"
+ #endif
+ ;
+ s.Add_LF();
}
+ // s += "GIPS GIPS GIPS % s"; s.Add_LF();
+ for (unsigned i = 0; i < RatingVector.Size(); i++)
+ {
+ if (i != 0)
+ s.Add_LF();
+ if ((int)i == sd.RatingVector_DeletedIndex)
+ {
+ s += "...";
+ s.Add_LF();
+ }
+ const CBenchPassResult &pair = RatingVector[i];
+ /*
+ s += "g:"; s.Add_UInt32((UInt32)pair.EncInfo.GlobalTime);
+ s += " u:"; s.Add_UInt32((UInt32)pair.EncInfo.UserTime);
+ s += " ";
+ */
+ AddRatingsLine(s, pair.Enc, pair.Dec
+ #ifdef PRINT_ITER_TIME
+ , pair.Ticks
+ #endif
+ );
+ /*
+ {
+ UInt64 v = i + 1;
+ if (sd.RatingVector_DeletedIndex >= 0 && i >= (unsigned)sd.RatingVector_DeletedIndex)
+ v += sd.RatingVector_NumDeleted;
+ char temp[64];
+ ConvertUInt64ToString(v, temp);
+ s += " : ";
+ s += temp;
+ }
+ */
+ }
+
+ if (sd.BenchWasFinished)
+ {
+ s.Add_LF();
+ s += "-------------";
+ s.Add_LF();
+ {
+ // average time is not correct because of freq detection in first iteration
+ AddRatingsLine(s, sd.Enc_BenchRes, sd.Dec_BenchRes
+ #ifdef PRINT_ITER_TIME
+ , (DWORD)(sd.TotalTicks / (sd.NumPasses_Finished ? sd.NumPasses_Finished : 1))
+ #endif
+ );
+ }
+ }
+ // s.Add_LF(); s += "OnTimer: "; s.Add_UInt32(k_OnTimer_cnt);
+ // s.Add_LF(); s += "finished Message: "; s.Add_UInt32(k_Message_Finished_cnt);
+ // static cnt = 0; cnt++; s.Add_LF(); s += "Print: "; s.Add_UInt32(cnt);
+ // s.Add_LF(); s += "NumEncProgress: "; s.Add_UInt32((UInt32)sd.NumEncProgress);
+ // s.Add_LF(); s += "NumDecProgress: "; s.Add_UInt32((UInt32)sd.NumDecProgress);
+ SetItemText(IDT_BENCH_LOG, s);
}
- return true;
}
+
bool CBenchmarkDialog::OnCommand(int code, int itemID, LPARAM lParam)
{
if (code == CBN_SELCHANGE &&
(itemID == IDC_BENCH_DICTIONARY ||
+ itemID == IDC_BENCH_NUM_PASSES ||
itemID == IDC_BENCH_NUM_THREADS))
{
- OnChangeSettings();
+ RestartBenchmark();
return true;
}
return CModalDialog::OnCommand(code, itemID, lParam);
}
+
bool CBenchmarkDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
{
switch (buttonID)
{
case IDB_RESTART:
- OnRestartButton();
+ RestartBenchmark();
return true;
case IDB_STOP:
OnStopButton();
@@ -596,87 +1419,81 @@ bool CBenchmarkDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
}
-struct CThreadBenchmark
-{
- CBenchmarkDialog *BenchmarkDialog;
- DECL_EXTERNAL_CODECS_LOC_VARS2;
- // UInt32 dictionarySize;
- // UInt32 numThreads;
- HRESULT Process();
- HRESULT Result;
- static THREAD_FUNC_DECL MyThreadFunction(void *param)
- {
- ((CThreadBenchmark *)param)->Result = ((CThreadBenchmark *)param)->Process();
- return 0;
- }
-};
+
+
+
+// ---------- Benchmark Thread ----------
struct CBenchCallback: public IBenchCallback
{
- UInt32 dictionarySize;
+ UInt64 dictionarySize;
CBenchProgressSync *Sync;
+ CBenchmarkDialog *BenchmarkDialog;
- // void AddCpuFreq(UInt64 cpuFreq);
- HRESULT SetFreq(bool showFreq, UInt64 cpuFreq);
HRESULT SetEncodeResult(const CBenchInfo &info, bool final);
HRESULT SetDecodeResult(const CBenchInfo &info, bool final);
};
-/*
-void CBenchCallback::AddCpuFreq(UInt64 cpuFreq)
-{
- NSynchronization::CCriticalSectionLock lock(Sync->CS);
- {
- wchar_t s[32];
- ConvertUInt64ToString(cpuFreq, s);
- Sync->Freq.Add_Space_if_NotEmpty();
- Sync->Freq += s;
- Sync->FreqWasChanged = true;
- }
-}
-*/
-
-HRESULT CBenchCallback::SetFreq(bool /* showFreq */, UInt64 /* cpuFreq */)
-{
- return S_OK;
-}
-
HRESULT CBenchCallback::SetEncodeResult(const CBenchInfo &info, bool final)
{
- NSynchronization::CCriticalSectionLock lock(Sync->CS);
- if (Sync->Changed || Sync->Paused || Sync->Stopped)
- return E_ABORT;
- Sync->ProcessedSize = info.UnpackSize * info.NumIterations;
- if (final && Sync->CompressingInfo.GlobalTime == 0)
+ bool needPost = false;
{
- (CBenchInfo&)Sync->CompressingInfo = info;
- if (Sync->CompressingInfo.GlobalTime == 0)
- Sync->CompressingInfo.GlobalTime = 1;
+ NSynchronization::CCriticalSectionLock lock(Sync->CS);
+ if (Sync->Exit)
+ return E_ABORT;
+ CSyncData &sd = Sync->sd;
+ // sd.NumEncProgress++;
+ CTotalBenchRes2 &br = sd.Enc_BenchRes_1;
+ {
+ UInt64 dictSize = Sync->DictSize;
+ if (final)
+ {
+ // sd.EncInfo = info;
+ }
+ else
+ {
+ /* if (!final), then CBenchInfo::NumIterations means totalNumber of threads.
+ so we can reduce the dictionary */
+ if (dictSize > info.UnpackSize)
+ dictSize = info.UnpackSize;
+ }
+ br.Rating = info.GetRating_LzmaEnc(dictSize);
+ }
+ br.SetFrom_BenchInfo(info);
+ sd.NeedPrint_Enc_1 = true;
+ if (final)
+ {
+ sd.Enc_BenchRes.Update_With_Res2(br);
+ sd.NeedPrint_Enc = true;
+ needPost = true;
+ }
}
- else
- (CBenchInfo&)Sync->CompressingInfoTemp = info;
+
+ if (needPost)
+ BenchmarkDialog->PostMsg(k_Message_Finished, k_Msg_WPARM_Enc1_Finished);
return S_OK;
}
+
HRESULT CBenchCallback::SetDecodeResult(const CBenchInfo &info, bool final)
{
NSynchronization::CCriticalSectionLock lock(Sync->CS);
- if (Sync->Changed || Sync->Paused || Sync->Stopped)
+ if (Sync->Exit)
return E_ABORT;
- CBenchInfo info2 = info;
- if (final && Sync->DecompressingInfo.GlobalTime == 0)
- {
- (CBenchInfo&)Sync->DecompressingInfo = info2;
- if (Sync->DecompressingInfo.GlobalTime == 0)
- Sync->DecompressingInfo.GlobalTime = 1;
- }
- else
- (CBenchInfo&)Sync->DecompressingInfoTemp = info2;
+ CSyncData &sd = Sync->sd;
+ // sd.NumDecProgress++;
+ CTotalBenchRes2 &br = sd.Dec_BenchRes_1;
+ br.Rating = info.GetRating_LzmaDec();
+ br.SetFrom_BenchInfo(info);
+ sd.NeedPrint_Dec_1 = true;
+ if (final)
+ sd.Dec_BenchRes.Update_With_Res2(br);
return S_OK;
}
+
struct CBenchCallback2: public IBenchPrintCallback
{
CBenchProgressSync *Sync;
@@ -704,74 +1521,142 @@ void CBenchCallback2::NewLine()
HRESULT CBenchCallback2::CheckBreak()
{
- if (Sync->Changed || Sync->Paused || Sync->Stopped)
+ if (Sync->Exit)
return E_ABORT;
return S_OK;
}
-/*
struct CFreqCallback: public IBenchFreqCallback
{
- CBenchProgressSync *Sync;
+ CBenchmarkDialog *BenchmarkDialog;
- virtual void AddCpuFreq(UInt64 freq);
+ virtual HRESULT AddCpuFreq(unsigned numThreads, UInt64 freq, UInt64 usage);
+ virtual HRESULT FreqsFinished(unsigned numThreads);
};
-void CFreqCallback::AddCpuFreq(UInt64 freq)
+HRESULT CFreqCallback::AddCpuFreq(unsigned numThreads, UInt64 freq, UInt64 usage)
{
- NSynchronization::CCriticalSectionLock lock(Sync->CS);
- Sync->Freq = freq;
+ HRESULT res;
+ {
+ CBenchProgressSync &sync = BenchmarkDialog->Sync;
+ NSynchronization::CCriticalSectionLock lock(sync.CS);
+ UString &s = sync.FreqString_Sync;
+ if (sync.NumFreqThreadsPrev != numThreads)
+ {
+ sync.NumFreqThreadsPrev = numThreads;
+ if (!s.IsEmpty())
+ s.Add_LF();
+ s.Add_UInt32(numThreads);
+ s += "T Frequency (MHz):";
+ s.Add_LF();
+ }
+ s += " ";
+ if (numThreads != 1)
+ {
+ s.Add_UInt64(GetUsagePercents(usage));
+ s += '%';
+ s.Add_Space();
+ }
+ s.Add_UInt64(GetMips(freq));
+ // BenchmarkDialog->Sync.sd.NeedPrint_Freq = true;
+ res = sync.Exit ? E_ABORT : S_OK;
+ }
+ // BenchmarkDialog->PostMsg(k_Message_Finished, k_Msg_WPARM_Enc1_Finished);
+ return res;
+}
+
+HRESULT CFreqCallback::FreqsFinished(unsigned /* numThreads */)
+{
+ HRESULT res;
+ {
+ CBenchProgressSync &sync = BenchmarkDialog->Sync;
+ NSynchronization::CCriticalSectionLock lock(sync.CS);
+ sync.sd.NeedPrint_Freq = true;
+ BenchmarkDialog->PostMsg(k_Message_Finished, k_Msg_WPARM_Enc1_Finished);
+ res = sync.Exit ? E_ABORT : S_OK;
+ }
+ BenchmarkDialog->PostMsg(k_Message_Finished, k_Msg_WPARM_Enc1_Finished);
+ return res;
}
-*/
+// define USE_DUMMY only for debug
+// #define USE_DUMMY
+#ifdef USE_DUMMY
+static unsigned dummy = 1;
+static unsigned Dummy(unsigned limit)
+{
+ unsigned sum = 0;
+ for (unsigned k = 0; k < limit; k++)
+ {
+ sum += dummy;
+ if (sum == 0)
+ break;
+ }
+ return sum;
+}
+#endif
+
+
HRESULT CThreadBenchmark::Process()
{
+ /* the first benchmark pass can be slow,
+ if we run benchmark while the window is being created,
+ and (no freq detecion loop) && (dictionary is small) (-mtic is small) */
+
+ // Sleep(300); // for debug
+ #ifdef USE_DUMMY
+ Dummy(1000 * 1000 * 1000); // for debug
+ #endif
+
CBenchProgressSync &sync = BenchmarkDialog->Sync;
- sync.WaitCreating();
+ HRESULT finishHRESULT = S_OK;
+
try
{
- for (;;)
+ for (UInt32 passIndex = 0;; passIndex++)
{
- if (sync.WasStopped())
- return 0;
- if (sync.WasPaused())
- {
- Sleep(200);
- continue;
- }
- UInt32 dictionarySize;
+ // throw 1; // to debug
+ // throw CSystemException(E_INVALIDARG); // to debug
+
+ UInt64 dictionarySize;
UInt32 numThreads;
{
NSynchronization::CCriticalSectionLock lock(sync.CS);
- if (sync.Stopped || sync.Paused)
- continue;
- if (sync.Changed)
- sync.Init();
- dictionarySize = sync.DictionarySize;
+ if (sync.Exit)
+ break;
+ dictionarySize = sync.DictSize;
numThreads = sync.NumThreads;
- /*
- if (sync.CompressingInfo.GlobalTime != 0)
- sync.FirstPath = false;
- */
}
+
+ #ifdef PRINT_ITER_TIME
+ const DWORD startTick = GetTickCount();
+ #endif
CBenchCallback callback;
+
callback.dictionarySize = dictionarySize;
callback.Sync = &sync;
+ callback.BenchmarkDialog = BenchmarkDialog;
+
CBenchCallback2 callback2;
callback2.TotalMode = BenchmarkDialog->TotalMode;
callback2.Sync = &sync;
- // CFreqCallback freqCallback;
- // freqCallback.Sync = &sync;
+
+ CFreqCallback freqCallback;
+ freqCallback.BenchmarkDialog = BenchmarkDialog;
+
HRESULT result;
try
{
CObjectVector<CProperty> props;
+
+ props = BenchmarkDialog->Props;
+
if (BenchmarkDialog->TotalMode)
{
props = BenchmarkDialog->Props;
@@ -787,8 +1672,8 @@ HRESULT CThreadBenchmark::Process()
{
CProperty prop;
prop.Name = 'd';
- prop.Name.Add_UInt32(dictionarySize);
- prop.Name += 'b';
+ prop.Name.Add_UInt32((UInt32)(dictionarySize >> 10));
+ prop.Name += 'k';
props.Add(prop);
}
}
@@ -796,57 +1681,133 @@ HRESULT CThreadBenchmark::Process()
result = Bench(EXTERNAL_CODECS_LOC_VARS
BenchmarkDialog->TotalMode ? &callback2 : NULL,
BenchmarkDialog->TotalMode ? NULL : &callback,
- // &freqCallback,
- props, 1, false);
+ props, 1, false,
+ (!BenchmarkDialog->TotalMode) && passIndex == 0 ? &freqCallback: NULL);
- if (BenchmarkDialog->TotalMode)
- {
- sync.Stop();
- }
+ // result = S_FALSE; // for debug;
+ // throw 1;
}
catch(...)
{
result = E_FAIL;
}
+ #ifdef PRINT_ITER_TIME
+ const DWORD numTicks = GetTickCount() - startTick;
+ #endif
+
+ bool finished = true;
+
+ NSynchronization::CCriticalSectionLock lock(sync.CS);
+
if (result != S_OK)
{
- if (result != E_ABORT)
+ sync.BenchFinish_Task_HRESULT = result;
+ break;
+ }
+
+ {
+ CSyncData &sd = sync.sd;
+
+ sd.NumPasses_Finished++;
+ #ifdef PRINT_ITER_TIME
+ sd.TotalTicks += numTicks;
+ #endif
+
+ if (BenchmarkDialog->TotalMode)
+ break;
+
{
+ CTotalBenchRes tot_BenchRes = sd.Enc_BenchRes_1;
+ tot_BenchRes.Update_With_Res(sd.Dec_BenchRes_1);
+
+ sd.NeedPrint_RatingVector = true;
{
- NSynchronization::CCriticalSectionLock lock(sync.CS);
- sync.Pause();
+ CBenchPassResult pair;
+ // pair.EncInfo = sd.EncInfo; // for debug
+ pair.Enc = sd.Enc_BenchRes_1;
+ pair.Dec = sd.Dec_BenchRes_1;
+ #ifdef PRINT_ITER_TIME
+ pair.Ticks = numTicks;
+ #endif
+ sync.RatingVector.Add(pair);
+ // pair.Dec_Defined = true;
}
- UString message;
- if (result == S_FALSE)
- message = "Decoding error";
- else if (result == CLASS_E_CLASSNOTAVAILABLE)
- message = "Can't find 7z.dll";
- else
- message = HResultToMessage(result);
- BenchmarkDialog->MessageBoxError(message);
+ }
+
+ sd.NeedPrint_Dec = true;
+ sd.NeedPrint_Tot = true;
+
+ if (sync.RatingVector.Size() > kRatingVector_NumBundlesMax)
+ {
+ // sd.RatingVector_NumDeleted++;
+ sd.RatingVector_DeletedIndex = (int)(kRatingVector_NumBundlesMax / 4);
+ sync.RatingVector.Delete((unsigned)(sd.RatingVector_DeletedIndex));
+ }
+
+ if (sync.sd.NumPasses_Finished < sync.NumPasses_Limit)
+ finished = false;
+ else
+ {
+ sync.sd.BenchWasFinished = true;
+ // BenchmarkDialog->_finishTime = GetTickCount();
+ // return 0;
}
}
- else
+
+ if (BenchmarkDialog->TotalMode)
+ break;
+
+ /*
+ if (newTick - prevTick < 1000)
+ numSameTick++;
+ if (numSameTick > 5 || finished)
{
- NSynchronization::CCriticalSectionLock lock(sync.CS);
- sync.NumPasses++;
+ prevTick = newTick;
+ numSameTick = 0;
+ */
+ // for (unsigned i = 0; i < 1; i++)
+ {
+ // we suppose that PostMsg messages will be processed in order.
+ if (!BenchmarkDialog->PostMsg_Finish(k_Msg_WPARM_Iter_Finished))
+ {
+ finished = true;
+ finishHRESULT = E_FAIL;
+ // throw 1234567;
+ }
}
+ if (finished)
+ break;
}
// return S_OK;
}
catch(CSystemException &e)
{
- BenchmarkDialog->MessageBoxError(HResultToMessage(e.ErrorCode));
- return E_FAIL;
+ finishHRESULT = e.ErrorCode;
+ // BenchmarkDialog->MessageBoxError(HResultToMessage(e.ErrorCode));
+ // return E_FAIL;
}
catch(...)
{
- BenchmarkDialog->MessageBoxError(HResultToMessage(E_FAIL));
- return E_FAIL;
+ finishHRESULT = E_FAIL;
+ // BenchmarkDialog->MessageBoxError(HResultToMessage(E_FAIL));
+ // return E_FAIL;
+ }
+
+ if (finishHRESULT != S_OK)
+ {
+ NSynchronization::CCriticalSectionLock lock(sync.CS);
+ sync.BenchFinish_Thread_HRESULT = finishHRESULT;
}
+ if (!BenchmarkDialog->PostMsg_Finish(k_Msg_WPARM_Thread_Finished))
+ {
+ // sync.BenchFinish_Thread_HRESULT = E_FAIL;
+ }
+ return 0;
}
+
+
static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop)
{
const wchar_t *end;
@@ -859,20 +1820,21 @@ static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop)
prop = result;
}
+
HRESULT Benchmark(
DECL_EXTERNAL_CODECS_LOC_VARS
- const CObjectVector<CProperty> &props, HWND hwndParent)
+ const CObjectVector<CProperty> &props, UInt32 numIterations, HWND hwndParent)
{
- CThreadBenchmark benchmarker;
- #ifdef EXTERNAL_CODECS
- benchmarker.__externalCodecs = __externalCodecs;
- #endif
-
CBenchmarkDialog bd;
- bd.Props = props;
+
bd.TotalMode = false;
- bd.Sync.DictionarySize = (UInt32)(Int32)-1;
+ bd.Props = props;
+ if (numIterations == 0)
+ numIterations = 1;
+ bd.Sync.NumPasses_Limit = numIterations;
+ bd.Sync.DictSize = (UInt64)(Int64)-1;
bd.Sync.NumThreads = (UInt32)(Int32)-1;
+ bd.Sync.Level = -1;
COneMethodInfo method;
@@ -905,13 +1867,17 @@ HRESULT Benchmark(
#endif
continue;
}
- if (name.IsEqualTo("testtime"))
+ /*
+ if (name.IsEqualTo("time"))
{
// UInt32 testTime = 4;
// RINOK(ParsePropToUInt32(L"", propVariant, testTime));
continue;
}
RINOK(method.ParseMethodFromPROPVARIANT(name, propVariant));
+ */
+ // here we need to parse DictSize property, and ignore unknown properties
+ method.ParseMethodFromPROPVARIANT(name, propVariant);
}
if (bd.TotalMode)
@@ -923,17 +1889,37 @@ HRESULT Benchmark(
}
{
- UInt32 dict;
+ UInt64 dict;
if (method.Get_DicSize(dict))
- bd.Sync.DictionarySize = dict;
+ bd.Sync.DictSize = dict;
+ }
+ bd.Sync.Level = method.GetLevel();
+
+ // Dummy(1000 * 1000 * 1);
+
+ {
+ CThreadBenchmark &benchmarker = bd._threadBenchmark;
+ #ifdef EXTERNAL_CODECS
+ benchmarker.__externalCodecs = __externalCodecs;
+ #endif
+ benchmarker.BenchmarkDialog = &bd;
}
- benchmarker.BenchmarkDialog = &bd;
+ bd.Create(hwndParent);
+ return S_OK;
+}
+
+
+CBenchmarkDialog::~CBenchmarkDialog()
+{
+ if (_thread.IsCreated())
{
- NWindows::CThread thread;
- RINOK(thread.Create(CThreadBenchmark::MyThreadFunction, &benchmarker));
- bd.Create(hwndParent);
- return thread.Wait_Close();
+ /* the following code will be not executed in normal code flow.
+ it can be called, if there is some internal failure in dialog code. */
+ Attach(NULL);
+ MessageBoxError(L"The flaw in benchmark thread code");
+ Sync.SendExit();
+ _thread.Wait_Close();
}
}