842 lines
20 KiB
C++
842 lines
20 KiB
C++
|
// BenchmarkDialog.cpp
|
||
|
|
||
|
#include "StdAfx.h"
|
||
|
|
||
|
#include "../../../../C/CpuArch.h"
|
||
|
|
||
|
#include "../../../Common/Defs.h"
|
||
|
#include "../../../Common/IntToString.h"
|
||
|
#include "../../../Common/MyException.h"
|
||
|
#include "../../../Common/StringConvert.h"
|
||
|
#include "../../../Common/StringToInt.h"
|
||
|
|
||
|
#include "../../../Windows/System.h"
|
||
|
#include "../../../Windows/Thread.h"
|
||
|
|
||
|
#include "../../Common/MethodProps.h"
|
||
|
|
||
|
#include "../FileManager/HelpUtils.h"
|
||
|
|
||
|
#include "../../MyVersion.h"
|
||
|
|
||
|
#include "BenchmarkDialog.h"
|
||
|
|
||
|
using namespace NWindows;
|
||
|
|
||
|
void GetCpuName(AString &s);
|
||
|
|
||
|
static LPCWSTR kHelpTopic = L"fm/benchmark.htm";
|
||
|
|
||
|
static const UINT_PTR kTimerID = 4;
|
||
|
static const UINT kTimerElapse = 1000;
|
||
|
|
||
|
#ifdef LANG
|
||
|
#include "../FileManager/LangUtils.h"
|
||
|
#endif
|
||
|
|
||
|
using namespace NWindows;
|
||
|
|
||
|
UString HResultToMessage(HRESULT errorCode);
|
||
|
|
||
|
#ifdef LANG
|
||
|
static const UInt32 kLangIDs[] =
|
||
|
{
|
||
|
IDT_BENCH_DICTIONARY,
|
||
|
IDT_BENCH_MEMORY,
|
||
|
IDT_BENCH_NUM_THREADS,
|
||
|
IDT_BENCH_SPEED,
|
||
|
IDT_BENCH_RATING_LABEL,
|
||
|
IDT_BENCH_USAGE_LABEL,
|
||
|
IDT_BENCH_RPU_LABEL,
|
||
|
IDG_BENCH_COMPRESSING,
|
||
|
IDG_BENCH_DECOMPRESSING,
|
||
|
IDG_BENCH_TOTAL_RATING,
|
||
|
IDT_BENCH_CURRENT,
|
||
|
IDT_BENCH_RESULTING,
|
||
|
IDT_BENCH_ELAPSED,
|
||
|
IDT_BENCH_PASSES,
|
||
|
IDB_STOP,
|
||
|
IDB_RESTART
|
||
|
};
|
||
|
|
||
|
static const UInt32 kLangIDs_Colon[] =
|
||
|
{
|
||
|
IDT_BENCH_SIZE
|
||
|
};
|
||
|
|
||
|
#endif
|
||
|
|
||
|
static const LPCTSTR kProcessingString = TEXT("...");
|
||
|
static const LPCTSTR kMB = TEXT(" MB");
|
||
|
static const LPCTSTR kMIPS = TEXT(" MIPS");
|
||
|
static const LPCTSTR kKBs = TEXT(" KB/s");
|
||
|
|
||
|
static const unsigned kMinDicLogSize =
|
||
|
#ifdef UNDER_CE
|
||
|
20;
|
||
|
#else
|
||
|
21;
|
||
|
#endif
|
||
|
|
||
|
static const UInt32 kMinDicSize = (1 << kMinDicLogSize);
|
||
|
static const UInt32 kMaxDicSize =
|
||
|
#ifdef MY_CPU_64BIT
|
||
|
(1 << 30);
|
||
|
#else
|
||
|
(1 << 27);
|
||
|
#endif
|
||
|
|
||
|
bool CBenchmarkDialog::OnInit()
|
||
|
{
|
||
|
#ifdef LANG
|
||
|
LangSetWindowText(*this, IDD_BENCH);
|
||
|
LangSetDlgItems(*this, kLangIDs, ARRAY_SIZE(kLangIDs));
|
||
|
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();
|
||
|
|
||
|
#ifdef _WIN32
|
||
|
if (TotalMode)
|
||
|
{
|
||
|
_consoleEdit.Attach(GetItem(IDE_BENCH2_EDIT));
|
||
|
LOGFONT f;
|
||
|
memset(&f, 0, sizeof(f));
|
||
|
f.lfHeight = 14;
|
||
|
f.lfWidth = 0;
|
||
|
f.lfWeight = FW_DONTCARE;
|
||
|
f.lfCharSet = DEFAULT_CHARSET;
|
||
|
f.lfOutPrecision = OUT_DEFAULT_PRECIS;
|
||
|
f.lfClipPrecision = CLIP_DEFAULT_PRECIS;
|
||
|
f.lfQuality = DEFAULT_QUALITY;
|
||
|
|
||
|
f.lfPitchAndFamily = FIXED_PITCH;
|
||
|
// MyStringCopy(f.lfFaceName, TEXT(""));
|
||
|
// f.lfFaceName[0] = 0;
|
||
|
_font.Create(&f);
|
||
|
if (_font._font)
|
||
|
_consoleEdit.SendMsg(WM_SETFONT, (WPARAM)_font._font, TRUE);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
{
|
||
|
TCHAR s[40];
|
||
|
s[0] = '/';
|
||
|
s[1] = ' ';
|
||
|
ConvertUInt32ToString(NSystem::GetNumberOfProcessors(), s + 2);
|
||
|
SetItemText(IDT_BENCH_HARDWARE_THREADS, s);
|
||
|
}
|
||
|
|
||
|
{
|
||
|
UString s;
|
||
|
{
|
||
|
AString cpuName;
|
||
|
GetCpuName(cpuName);
|
||
|
s.SetFromAscii(cpuName);
|
||
|
SetItemText(IDT_BENCH_CPU, s);
|
||
|
}
|
||
|
|
||
|
s.SetFromAscii("7-Zip " MY_VERSION " ["
|
||
|
#ifdef MY_CPU_64BIT
|
||
|
"64-bit"
|
||
|
#elif defined MY_CPU_32BIT
|
||
|
"32-bit"
|
||
|
#endif
|
||
|
"]");
|
||
|
SetItemText(IDT_BENCH_VER, s);
|
||
|
}
|
||
|
|
||
|
|
||
|
UInt32 numCPUs = NSystem::GetNumberOfProcessors();
|
||
|
if (numCPUs < 1)
|
||
|
numCPUs = 1;
|
||
|
numCPUs = MyMin(numCPUs, (UInt32)(1 << 8));
|
||
|
|
||
|
if (Sync.NumThreads == (UInt32)(Int32)-1)
|
||
|
{
|
||
|
Sync.NumThreads = numCPUs;
|
||
|
if (Sync.NumThreads > 1)
|
||
|
Sync.NumThreads &= ~1;
|
||
|
}
|
||
|
m_NumThreads.Attach(GetItem(IDC_BENCH_NUM_THREADS));
|
||
|
int cur = 0;
|
||
|
for (UInt32 num = 1; num <= numCPUs * 2;)
|
||
|
{
|
||
|
TCHAR s[16];
|
||
|
ConvertUInt32ToString(num, s);
|
||
|
int index = (int)m_NumThreads.AddString(s);
|
||
|
m_NumThreads.SetItemData(index, num);
|
||
|
if (num <= Sync.NumThreads)
|
||
|
cur = index;
|
||
|
if (num > 1)
|
||
|
num++;
|
||
|
num++;
|
||
|
}
|
||
|
m_NumThreads.SetCurSel(cur);
|
||
|
Sync.NumThreads = GetNumberOfThreads();
|
||
|
|
||
|
m_Dictionary.Attach(GetItem(IDC_BENCH_DICTIONARY));
|
||
|
cur = 0;
|
||
|
|
||
|
UInt64 ramSize = (UInt64)(sizeof(size_t)) << 29;
|
||
|
bool ramSize_Defined = NSystem::GetRamSize(ramSize);
|
||
|
|
||
|
#ifdef UNDER_CE
|
||
|
const UInt32 kNormalizedCeSize = (16 << 20);
|
||
|
if (ramSize > kNormalizedCeSize && ramSize < (33 << 20))
|
||
|
ramSize = kNormalizedCeSize;
|
||
|
#endif
|
||
|
|
||
|
if (Sync.DictionarySize == (UInt32)(Int32)-1)
|
||
|
{
|
||
|
unsigned dicSizeLog = 25;
|
||
|
|
||
|
#ifdef UNDER_CE
|
||
|
dicSizeLog = 20;
|
||
|
#endif
|
||
|
|
||
|
if (ramSize_Defined)
|
||
|
for (; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--)
|
||
|
if (GetBenchMemoryUsage(Sync.NumThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize)
|
||
|
break;
|
||
|
Sync.DictionarySize = (1 << dicSizeLog);
|
||
|
}
|
||
|
|
||
|
if (Sync.DictionarySize < kMinDicSize) Sync.DictionarySize = kMinDicSize;
|
||
|
if (Sync.DictionarySize > kMaxDicSize) Sync.DictionarySize = kMaxDicSize;
|
||
|
|
||
|
for (unsigned i = kMinDicLogSize; i <= 30; i++)
|
||
|
for (unsigned j = 0; j < 2; j++)
|
||
|
{
|
||
|
UInt32 dict = (1 << i) + (j << (i - 1));
|
||
|
if (dict > kMaxDicSize)
|
||
|
continue;
|
||
|
TCHAR s[16];
|
||
|
ConvertUInt32ToString((dict >> 20), s);
|
||
|
lstrcat(s, kMB);
|
||
|
int index = (int)m_Dictionary.AddString(s);
|
||
|
m_Dictionary.SetItemData(index, dict);
|
||
|
if (dict <= Sync.DictionarySize)
|
||
|
cur = index;
|
||
|
}
|
||
|
m_Dictionary.SetCurSel(cur);
|
||
|
|
||
|
OnChangeSettings();
|
||
|
|
||
|
Sync._startEvent.Set();
|
||
|
_timer = SetTimer(kTimerID, kTimerElapse);
|
||
|
|
||
|
if (TotalMode)
|
||
|
NormalizeSize(true);
|
||
|
else
|
||
|
NormalizePosition();
|
||
|
return CModalDialog::OnInit();
|
||
|
}
|
||
|
|
||
|
#ifdef _WIN32
|
||
|
bool CBenchmarkDialog::OnSize(WPARAM /* wParam */, int xSize, int ySize)
|
||
|
{
|
||
|
if (!TotalMode)
|
||
|
return false;
|
||
|
int mx, my;
|
||
|
GetMargins(8, mx, my);
|
||
|
int bx1, bx2, by;
|
||
|
GetItemSizes(IDCANCEL, bx1, by);
|
||
|
GetItemSizes(IDHELP, bx2, by);
|
||
|
|
||
|
{
|
||
|
int y = ySize - my - by;
|
||
|
int x = xSize - mx - bx1;
|
||
|
|
||
|
InvalidateRect(NULL);
|
||
|
|
||
|
MoveItem(IDCANCEL, x, y, bx1, by);
|
||
|
MoveItem(IDHELP, x - mx - bx2, y, bx2, by);
|
||
|
}
|
||
|
|
||
|
if (_consoleEdit)
|
||
|
{
|
||
|
int yPos = ySize - my - by;
|
||
|
RECT rect;
|
||
|
GetClientRectOfItem(IDE_BENCH2_EDIT, rect);
|
||
|
int y = rect.top;
|
||
|
int ySize2 = yPos - my - y;
|
||
|
const int kMinYSize = 20;
|
||
|
int xx = xSize - mx * 2;
|
||
|
if (ySize2 < kMinYSize)
|
||
|
{
|
||
|
ySize2 = kMinYSize;
|
||
|
}
|
||
|
_consoleEdit.Move(mx, y, xx, ySize2);
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
UInt32 CBenchmarkDialog::GetNumberOfThreads()
|
||
|
{
|
||
|
return (UInt32)m_NumThreads.GetItemData_of_CurSel();
|
||
|
}
|
||
|
|
||
|
UInt32 CBenchmarkDialog::OnChangeDictionary()
|
||
|
{
|
||
|
UInt32 dict = (UInt32)m_Dictionary.GetItemData_of_CurSel();
|
||
|
UInt64 memUsage = GetBenchMemoryUsage(GetNumberOfThreads(), dict);
|
||
|
memUsage = (memUsage + (1 << 20) - 1) >> 20;
|
||
|
TCHAR s[40];
|
||
|
ConvertUInt64ToString(memUsage, s);
|
||
|
lstrcat(s, kMB);
|
||
|
SetItemText(IDT_BENCH_MEMORY_VAL, s);
|
||
|
return dict;
|
||
|
}
|
||
|
|
||
|
static const UInt32 g_IDs[] =
|
||
|
{
|
||
|
IDT_BENCH_COMPRESS_USAGE1,
|
||
|
IDT_BENCH_COMPRESS_USAGE2,
|
||
|
IDT_BENCH_COMPRESS_SPEED1,
|
||
|
IDT_BENCH_COMPRESS_SPEED2,
|
||
|
IDT_BENCH_COMPRESS_RATING1,
|
||
|
IDT_BENCH_COMPRESS_RATING2,
|
||
|
IDT_BENCH_COMPRESS_RPU1,
|
||
|
IDT_BENCH_COMPRESS_RPU2,
|
||
|
|
||
|
IDT_BENCH_DECOMPR_SPEED1,
|
||
|
IDT_BENCH_DECOMPR_SPEED2,
|
||
|
IDT_BENCH_DECOMPR_RATING1,
|
||
|
IDT_BENCH_DECOMPR_RATING2,
|
||
|
IDT_BENCH_DECOMPR_USAGE1,
|
||
|
IDT_BENCH_DECOMPR_USAGE2,
|
||
|
IDT_BENCH_DECOMPR_RPU1,
|
||
|
IDT_BENCH_DECOMPR_RPU2,
|
||
|
|
||
|
IDT_BENCH_TOTAL_USAGE_VAL,
|
||
|
IDT_BENCH_TOTAL_RATING_VAL,
|
||
|
IDT_BENCH_TOTAL_RPU_VAL
|
||
|
};
|
||
|
|
||
|
void CBenchmarkDialog::OnChangeSettings()
|
||
|
{
|
||
|
EnableItem(IDB_STOP, true);
|
||
|
UInt32 dict = OnChangeDictionary();
|
||
|
|
||
|
for (int i = 0; i < ARRAY_SIZE(g_IDs); i++)
|
||
|
SetItemText(g_IDs[i], kProcessingString);
|
||
|
_startTime = GetTickCount();
|
||
|
PrintTime();
|
||
|
NWindows::NSynchronization::CCriticalSectionLock lock(Sync.CS);
|
||
|
Sync.Init();
|
||
|
Sync.DictionarySize = dict;
|
||
|
Sync.Changed = true;
|
||
|
Sync.NumThreads = GetNumberOfThreads();
|
||
|
}
|
||
|
|
||
|
void CBenchmarkDialog::OnRestartButton()
|
||
|
{
|
||
|
OnChangeSettings();
|
||
|
}
|
||
|
|
||
|
void CBenchmarkDialog::OnStopButton()
|
||
|
{
|
||
|
EnableItem(IDB_STOP, false);
|
||
|
Sync.Pause();
|
||
|
}
|
||
|
|
||
|
void CBenchmarkDialog::OnHelp()
|
||
|
{
|
||
|
ShowHelpWindow(NULL, kHelpTopic);
|
||
|
}
|
||
|
|
||
|
void CBenchmarkDialog::OnCancel()
|
||
|
{
|
||
|
Sync.Stop();
|
||
|
KillTimer(_timer);
|
||
|
CModalDialog::OnCancel();
|
||
|
}
|
||
|
|
||
|
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())
|
||
|
return;
|
||
|
WCHAR s[40];
|
||
|
GetTimeString(elapsedSec, s);
|
||
|
SetItemText(IDT_BENCH_ELAPSED_VAL, s);
|
||
|
}
|
||
|
|
||
|
void CBenchmarkDialog::PrintRating(UInt64 rating, UINT controlID)
|
||
|
{
|
||
|
TCHAR s[40];
|
||
|
ConvertUInt64ToString(rating / 1000000, s);
|
||
|
lstrcat(s, kMIPS);
|
||
|
SetItemText(controlID, s);
|
||
|
}
|
||
|
|
||
|
void CBenchmarkDialog::PrintUsage(UInt64 usage, UINT controlID)
|
||
|
{
|
||
|
TCHAR s[40];
|
||
|
ConvertUInt64ToString((usage + 5000) / 10000, s);
|
||
|
lstrcat(s, TEXT("%"));
|
||
|
SetItemText(controlID, s);
|
||
|
}
|
||
|
|
||
|
void CBenchmarkDialog::PrintResults(
|
||
|
UInt32 dictionarySize,
|
||
|
const CBenchInfo2 &info,
|
||
|
UINT usageID, UINT speedID, UINT rpuID, UINT ratingID,
|
||
|
bool decompressMode)
|
||
|
{
|
||
|
if (info.GlobalTime == 0)
|
||
|
return;
|
||
|
|
||
|
TCHAR s[40];
|
||
|
{
|
||
|
UInt64 speed = info.UnpackSize * info.NumIterations * info.GlobalFreq / info.GlobalTime;
|
||
|
ConvertUInt64ToString(speed / 1024, s);
|
||
|
lstrcat(s, kKBs);
|
||
|
SetItemText(speedID, s);
|
||
|
}
|
||
|
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 */)
|
||
|
{
|
||
|
bool printTime = true;
|
||
|
if (TotalMode)
|
||
|
{
|
||
|
if (Sync.WasStopped())
|
||
|
printTime = false;
|
||
|
}
|
||
|
if (printTime)
|
||
|
PrintTime();
|
||
|
NWindows::NSynchronization::CCriticalSectionLock lock(Sync.CS);
|
||
|
|
||
|
if (TotalMode)
|
||
|
{
|
||
|
if (Sync.TextWasChanged)
|
||
|
{
|
||
|
_consoleEdit.SetText(GetSystemString(Sync.Text));
|
||
|
Sync.TextWasChanged = false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
TCHAR s[40];
|
||
|
ConvertUInt64ToString((Sync.ProcessedSize >> 20), s);
|
||
|
lstrcat(s, kMB);
|
||
|
SetItemText(IDT_BENCH_SIZE_VAL, s);
|
||
|
|
||
|
ConvertUInt64ToString(Sync.NumPasses, s);
|
||
|
SetItemText(IDT_BENCH_PASSES_VAL, s);
|
||
|
|
||
|
/*
|
||
|
if (Sync.FreqWasChanged)
|
||
|
{
|
||
|
SetItemText(IDT_BENCH_FREQ, Sync.Freq);
|
||
|
Sync.FreqWasChanged = false;
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
{
|
||
|
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);
|
||
|
}
|
||
|
|
||
|
{
|
||
|
PrintResults(
|
||
|
Sync.DictionarySize,
|
||
|
Sync.CompressingInfo,
|
||
|
IDT_BENCH_COMPRESS_USAGE2,
|
||
|
IDT_BENCH_COMPRESS_SPEED2,
|
||
|
IDT_BENCH_COMPRESS_RPU2,
|
||
|
IDT_BENCH_COMPRESS_RATING2);
|
||
|
}
|
||
|
|
||
|
{
|
||
|
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)
|
||
|
{
|
||
|
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);
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool CBenchmarkDialog::OnCommand(int code, int itemID, LPARAM lParam)
|
||
|
{
|
||
|
if (code == CBN_SELCHANGE &&
|
||
|
(itemID == IDC_BENCH_DICTIONARY ||
|
||
|
itemID == IDC_BENCH_NUM_THREADS))
|
||
|
{
|
||
|
OnChangeSettings();
|
||
|
return true;
|
||
|
}
|
||
|
return CModalDialog::OnCommand(code, itemID, lParam);
|
||
|
}
|
||
|
|
||
|
bool CBenchmarkDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
|
||
|
{
|
||
|
switch (buttonID)
|
||
|
{
|
||
|
case IDB_RESTART:
|
||
|
OnRestartButton();
|
||
|
return true;
|
||
|
case IDB_STOP:
|
||
|
OnStopButton();
|
||
|
return true;
|
||
|
}
|
||
|
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;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
struct CBenchCallback: public IBenchCallback
|
||
|
{
|
||
|
UInt32 dictionarySize;
|
||
|
CProgressSyncInfo *Sync;
|
||
|
|
||
|
// 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)
|
||
|
{
|
||
|
(CBenchInfo&)Sync->CompressingInfo = info;
|
||
|
if (Sync->CompressingInfo.GlobalTime == 0)
|
||
|
Sync->CompressingInfo.GlobalTime = 1;
|
||
|
}
|
||
|
else
|
||
|
(CBenchInfo&)Sync->CompressingInfoTemp = info;
|
||
|
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
HRESULT CBenchCallback::SetDecodeResult(const CBenchInfo &info, bool final)
|
||
|
{
|
||
|
NSynchronization::CCriticalSectionLock lock(Sync->CS);
|
||
|
if (Sync->Changed || Sync->Paused || Sync->Stopped)
|
||
|
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;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
struct CBenchCallback2: public IBenchPrintCallback
|
||
|
{
|
||
|
CProgressSyncInfo *Sync;
|
||
|
|
||
|
void Print(const char *s);
|
||
|
void NewLine();
|
||
|
HRESULT CheckBreak();
|
||
|
};
|
||
|
|
||
|
void CBenchCallback2::Print(const char *s)
|
||
|
{
|
||
|
NSynchronization::CCriticalSectionLock lock(Sync->CS);
|
||
|
Sync->Text += s;
|
||
|
Sync->TextWasChanged = true;
|
||
|
}
|
||
|
|
||
|
void CBenchCallback2::NewLine()
|
||
|
{
|
||
|
Print("\xD\n");
|
||
|
}
|
||
|
|
||
|
HRESULT CBenchCallback2::CheckBreak()
|
||
|
{
|
||
|
if (Sync->Changed || Sync->Paused || Sync->Stopped)
|
||
|
return E_ABORT;
|
||
|
return S_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
HRESULT CThreadBenchmark::Process()
|
||
|
{
|
||
|
CProgressSyncInfo &sync = BenchmarkDialog->Sync;
|
||
|
sync.WaitCreating();
|
||
|
try
|
||
|
{
|
||
|
for (;;)
|
||
|
{
|
||
|
if (sync.WasStopped())
|
||
|
return 0;
|
||
|
if (sync.WasPaused())
|
||
|
{
|
||
|
Sleep(200);
|
||
|
continue;
|
||
|
}
|
||
|
UInt32 dictionarySize;
|
||
|
UInt32 numThreads;
|
||
|
{
|
||
|
NSynchronization::CCriticalSectionLock lock(sync.CS);
|
||
|
if (sync.Stopped || sync.Paused)
|
||
|
continue;
|
||
|
if (sync.Changed)
|
||
|
sync.Init();
|
||
|
dictionarySize = sync.DictionarySize;
|
||
|
numThreads = sync.NumThreads;
|
||
|
}
|
||
|
|
||
|
CBenchCallback callback;
|
||
|
callback.dictionarySize = dictionarySize;
|
||
|
callback.Sync = &sync;
|
||
|
CBenchCallback2 callback2;
|
||
|
callback2.Sync = &sync;
|
||
|
HRESULT result;
|
||
|
|
||
|
try
|
||
|
{
|
||
|
CObjectVector<CProperty> props;
|
||
|
if (BenchmarkDialog->TotalMode)
|
||
|
{
|
||
|
props = BenchmarkDialog->Props;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
{
|
||
|
CProperty prop;
|
||
|
prop.Name = L"mt";
|
||
|
wchar_t s[16];
|
||
|
ConvertUInt32ToString(numThreads, s);
|
||
|
prop.Value = s;
|
||
|
props.Add(prop);
|
||
|
}
|
||
|
{
|
||
|
CProperty prop;
|
||
|
prop.Name = L'd';
|
||
|
wchar_t s[16];
|
||
|
ConvertUInt32ToString(dictionarySize, s);
|
||
|
prop.Name += s;
|
||
|
prop.Name += L'b';
|
||
|
props.Add(prop);
|
||
|
}
|
||
|
}
|
||
|
result = Bench(EXTERNAL_CODECS_LOC_VARS
|
||
|
BenchmarkDialog->TotalMode ? &callback2 : NULL,
|
||
|
BenchmarkDialog->TotalMode ? NULL : &callback,
|
||
|
props, 1, false);
|
||
|
if (BenchmarkDialog->TotalMode)
|
||
|
{
|
||
|
sync.Stop();
|
||
|
}
|
||
|
}
|
||
|
catch(...)
|
||
|
{
|
||
|
result = E_FAIL;
|
||
|
}
|
||
|
|
||
|
if (result != S_OK)
|
||
|
{
|
||
|
if (result != E_ABORT)
|
||
|
{
|
||
|
{
|
||
|
NSynchronization::CCriticalSectionLock lock(sync.CS);
|
||
|
sync.Pause();
|
||
|
}
|
||
|
UString message;
|
||
|
if (result == S_FALSE)
|
||
|
message = L"Decoding error";
|
||
|
else if (result == CLASS_E_CLASSNOTAVAILABLE)
|
||
|
message = L"Can't find 7z.dll";
|
||
|
else
|
||
|
message = HResultToMessage(result);
|
||
|
BenchmarkDialog->MessageBoxError(message);
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
NSynchronization::CCriticalSectionLock lock(sync.CS);
|
||
|
sync.NumPasses++;
|
||
|
}
|
||
|
}
|
||
|
// return S_OK;
|
||
|
}
|
||
|
catch(CSystemException &e)
|
||
|
{
|
||
|
BenchmarkDialog->MessageBoxError(HResultToMessage(e.ErrorCode));
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
catch(...)
|
||
|
{
|
||
|
BenchmarkDialog->MessageBoxError(HResultToMessage(E_FAIL));
|
||
|
return E_FAIL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void ParseNumberString(const UString &s, NCOM::CPropVariant &prop)
|
||
|
{
|
||
|
const wchar_t *end;
|
||
|
UInt64 result = ConvertStringToUInt64(s, &end);
|
||
|
if (*end != 0 || s.IsEmpty())
|
||
|
prop = s;
|
||
|
else if (result <= (UInt32)0xFFFFFFFF)
|
||
|
prop = (UInt32)result;
|
||
|
else
|
||
|
prop = result;
|
||
|
}
|
||
|
|
||
|
HRESULT Benchmark(
|
||
|
DECL_EXTERNAL_CODECS_LOC_VARS
|
||
|
const CObjectVector<CProperty> props, 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.Sync.NumThreads = (UInt32)(Int32)-1;
|
||
|
|
||
|
COneMethodInfo method;
|
||
|
|
||
|
UInt32 numCPUs = 1;
|
||
|
#ifndef _7ZIP_ST
|
||
|
numCPUs = NSystem::GetNumberOfProcessors();
|
||
|
#endif
|
||
|
UInt32 numThreads = numCPUs;
|
||
|
|
||
|
FOR_VECTOR (i, props)
|
||
|
{
|
||
|
const CProperty &prop = props[i];
|
||
|
UString name = prop.Name;
|
||
|
name.MakeLower_Ascii();
|
||
|
if (name.IsEqualTo_Ascii_NoCase("m") && prop.Value == L"*")
|
||
|
{
|
||
|
bd.TotalMode = true;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
NCOM::CPropVariant propVariant;
|
||
|
if (!prop.Value.IsEmpty())
|
||
|
ParseNumberString(prop.Value, propVariant);
|
||
|
if (name.IsPrefixedBy(L"mt"))
|
||
|
{
|
||
|
#ifndef _7ZIP_ST
|
||
|
RINOK(ParseMtProp(name.Ptr(2), propVariant, numCPUs, numThreads));
|
||
|
if (numThreads != numCPUs)
|
||
|
bd.Sync.NumThreads = numThreads;
|
||
|
#endif
|
||
|
continue;
|
||
|
}
|
||
|
if (name.IsEqualTo("testtime"))
|
||
|
{
|
||
|
// UInt32 testTime = 4;
|
||
|
// RINOK(ParsePropToUInt32(L"", propVariant, testTime));
|
||
|
continue;
|
||
|
}
|
||
|
RINOK(method.ParseMethodFromPROPVARIANT(name, propVariant));
|
||
|
}
|
||
|
|
||
|
// bool totalBenchMode = (method.MethodName == L"*");
|
||
|
|
||
|
{
|
||
|
UInt32 dict;
|
||
|
if (method.Get_DicSize(dict))
|
||
|
bd.Sync.DictionarySize = dict;
|
||
|
}
|
||
|
|
||
|
benchmarker.BenchmarkDialog = &bd;
|
||
|
|
||
|
NWindows::CThread thread;
|
||
|
RINOK(thread.Create(CThreadBenchmark::MyThreadFunction, &benchmarker));
|
||
|
bd.Create(hwndParent);
|
||
|
return thread.Wait();
|
||
|
}
|