📄 benchmarkdialog.cpp
字号:
}
bool CBenchmarkDialog::OnButtonClicked(int buttonID, HWND buttonHWND)
{
switch(buttonID)
{
case IDC_BUTTON_RESTART:
OnRestartButton();
return true;
case IDC_BUTTON_STOP:
OnStopButton();
return true;
case IDC_BENCHMARK_MULTITHREADING:
OnChangeSettings();
return true;
}
return CModalDialog::OnButtonClicked(buttonID, buttonHWND);
}
class CBenchmarkInStream:
public ISequentialInStream,
public CMyUnknownImp
{
const Byte *Data;
UInt32 Pos;
UInt32 Size;
public:
MY_UNKNOWN_IMP
void Init(const Byte *data, UInt32 size)
{
Data = data;
Size = size;
Pos = 0;
}
STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize);
};
STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
{
UInt32 remain = Size - Pos;
if (size > remain)
size = remain;
for (UInt32 i = 0; i < size; i++)
{
((Byte *)data)[i] = Data[Pos + i];
}
Pos += size;
if(processedSize != NULL)
*processedSize = size;
return S_OK;
}
STDMETHODIMP CBenchmarkInStream::ReadPart(void *data, UInt32 size, UInt32 *processedSize)
{
return Read(data, size, processedSize);
}
class CBenchmarkOutStream:
public ISequentialOutStream,
public CMyUnknownImp
{
UInt32 BufferSize;
public:
UInt32 Pos;
Byte *Buffer;
CBenchmarkOutStream(): Buffer(0) {}
~CBenchmarkOutStream() { delete []Buffer; }
void Init(UInt32 bufferSize)
{
delete []Buffer;
Buffer = 0;
Buffer = new Byte[bufferSize];
Pos = 0;
BufferSize = bufferSize;
}
MY_UNKNOWN_IMP
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize);
};
STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
UInt32 i;
for (i = 0; i < size && Pos < BufferSize; i++)
Buffer[Pos++] = ((const Byte *)data)[i];
if(processedSize != NULL)
*processedSize = i;
if (i != size)
{
MessageBoxW(0, L"Buffer is full", L"7-zip error", 0);
return E_FAIL;
}
return S_OK;
}
STDMETHODIMP CBenchmarkOutStream::WritePart(const void *data, UInt32 size, UInt32 *processedSize)
{
return Write(data, size, processedSize);
}
class CCompareOutStream:
public ISequentialOutStream,
public CMyUnknownImp
{
public:
CCRC CRC;
MY_UNKNOWN_IMP
void Init() { CRC.Init(); }
STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize);
};
STDMETHODIMP CCompareOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
{
CRC.Update(data, size);
if(processedSize != NULL)
*processedSize = size;
return S_OK;
}
STDMETHODIMP CCompareOutStream::WritePart(const void *data, UInt32 size, UInt32 *processedSize)
{
return Write(data, size, processedSize);
}
typedef UInt32 (WINAPI * CreateObjectPointer)(const GUID *clsID,
const GUID *interfaceID, void **outObject);
struct CDecoderProgressInfo:
public ICompressProgressInfo,
public CMyUnknownImp
{
CProgressSyncInfo *SyncInfo;
MY_UNKNOWN_IMP
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
};
STDMETHODIMP CDecoderProgressInfo::SetRatioInfo(
const UInt64 *inSize, const UInt64 *outSize)
{
NSynchronization::CCriticalSectionLock lock(SyncInfo->CS);
if (SyncInfo->Changed)
return E_ABORT;
return S_OK;
}
struct CThreadBenchmark:
public ICompressProgressInfo,
public CMyUnknownImp
{
CProgressSyncInfo *SyncInfo;
UInt64 _startTime;
UInt64 _approvedStart;
NDLL::CLibrary Library;
CMyComPtr<ICompressCoder> Encoder;
CMyComPtr<ICompressCoder> Decoder;
DWORD Process();
static DWORD WINAPI MyThreadFunction(void *param)
{
return ((CThreadBenchmark *)param)->Process();
}
MY_UNKNOWN_IMP
STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
};
DWORD CThreadBenchmark::Process()
{
try
{
SyncInfo->WaitCreating();
CBenchRandomGenerator randomGenerator;
randomGenerator.Init();
CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
Encoder.QueryInterface(IID_ICompressWriteCoderProperties,
&writeCoderProperties);
CMyComPtr<ICompressSetDecoderProperties2> compressSetDecoderProperties;
Decoder.QueryInterface(
IID_ICompressSetDecoderProperties2, &compressSetDecoderProperties);
CSequentialOutStreamImp *propStreamSpec = 0;
CMyComPtr<ISequentialOutStream> propStream;
if (writeCoderProperties != NULL)
{
propStreamSpec = new CSequentialOutStreamImp;
propStream = propStreamSpec;
}
CMyComPtr<ICompressSetCoderProperties> setCoderProperties;
Encoder.QueryInterface(IID_ICompressSetCoderProperties,
&setCoderProperties);
CDecoderProgressInfo *decoderProgressInfoSpec = new
CDecoderProgressInfo;
CMyComPtr<ICompressProgressInfo> decoderProgress = decoderProgressInfoSpec;
decoderProgressInfoSpec->SyncInfo = SyncInfo;
while(true)
{
if (SyncInfo->WasStopped())
return 0;
if (SyncInfo->WasPaused())
{
Sleep(200);
continue;
}
UInt32 dictionarySize;
bool multiThread;
{
NSynchronization::CCriticalSectionLock lock(SyncInfo->CS);
dictionarySize = SyncInfo->DictionarySize;
multiThread = SyncInfo->MultiThread;
if (SyncInfo->Changed)
SyncInfo->Init();
}
const UInt32 kBufferSize = dictionarySize + kAdditionalSize;
const UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize;
if (setCoderProperties)
{
PROPID propIDs[] =
{
NCoderPropID::kDictionarySize,
NCoderPropID::kMultiThread
};
const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);
NWindows::NCOM::CPropVariant properties[kNumProps];
properties[0] = UInt32(dictionarySize);
properties[1] = bool(multiThread);
RINOK(setCoderProperties->SetCoderProperties(propIDs,
properties, kNumProps));
}
if (propStream)
{
propStreamSpec->Init();
writeCoderProperties->WriteCoderProperties(propStream);
}
randomGenerator.Set(kBufferSize);
randomGenerator.Generate();
CCRC crc;
// randomGenerator.BufferSize
crc.Update(randomGenerator.Buffer, randomGenerator.BufferSize);
{
NSynchronization::CCriticalSectionLock lock(SyncInfo->CS);
if (SyncInfo->Changed)
continue;
}
CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream;
inStreamSpec->Init(randomGenerator.Buffer, randomGenerator.BufferSize);
CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
CBenchmarkOutStream *outStreamSpec = new CBenchmarkOutStream;
outStreamSpec->Init(kCompressedBufferSize);
CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
_approvedStart = dictionarySize;
_startTime = ::GetTimeCount();
HRESULT result = Encoder->Code(inStream, outStream, 0, 0, this);
UInt64 tickCount = ::GetTimeCount() - _startTime;
UInt32 compressedSize = outStreamSpec->Pos;
{
NSynchronization::CCriticalSectionLock lock(SyncInfo->CS);
if (result == S_OK)
{
if (SyncInfo->ApprovedInfo.InSize != 0)
{
SyncInfo->CompressingInfoTemp.InSize = kBufferSize - SyncInfo->ApprovedInfo.InSize;
SyncInfo->CompressingInfoTemp.OutSize = compressedSize - SyncInfo->ApprovedInfo.OutSize;
SyncInfo->CompressingInfoTemp.Time = tickCount - SyncInfo->ApprovedInfo.Time;
if (SyncInfo->CompressingInfo.Time == 0)
SyncInfo->CompressingInfo = SyncInfo->CompressingInfoTemp;
}
}
SyncInfo->ApprovedInfo.Init();
}
if(result != S_OK)
{
if (result != E_ABORT)
{
SyncInfo->Pause();
MessageBox(0, NError::MyFormatMessage(result), TEXT("7-Zip"), MB_ICONERROR);
}
continue;
}
{
NSynchronization::CCriticalSectionLock lock(SyncInfo->CS);
SyncInfo->NumPasses++;
}
///////////////////////
// Decompressing
CCompareOutStream *outCompareStreamSpec = new CCompareOutStream;
CMyComPtr<ISequentialOutStream> outCompareStream = outCompareStreamSpec;
for (int i = 0; i < 2; i++)
{
inStreamSpec->Init(outStreamSpec->Buffer, compressedSize);
outCompareStreamSpec->Init();
if (compressSetDecoderProperties)
{
RINOK(compressSetDecoderProperties->SetDecoderProperties2(
propStreamSpec->GetBuffer(), propStreamSpec->GetSize()));
}
UInt64 outSize = kBufferSize;
UInt64 startTime = ::GetTimeCount();
result = Decoder->Code(inStream, outCompareStream, 0, &outSize, decoderProgress);
tickCount = ::GetTimeCount() - startTime;
{
NSynchronization::CCriticalSectionLock lock(SyncInfo->CS);
if (result == S_OK)
{
SyncInfo->DecompressingInfoTemp.InSize = compressedSize;
SyncInfo->DecompressingInfoTemp.OutSize = kBufferSize;
SyncInfo->DecompressingInfoTemp.Time = tickCount;
if (SyncInfo->DecompressingInfo.Time == 0 && i >= 1)
SyncInfo->DecompressingInfo = SyncInfo->DecompressingInfoTemp;
if (outCompareStreamSpec->CRC.GetDigest() != crc.GetDigest())
{
SyncInfo->NumErrors++;
break;
}
}
else
{
if(result != E_ABORT)
{
SyncInfo->NumErrors++;
break;
}
}
}
}
}
}
catch(CSystemException &e)
{
MessageBox(0, NError::MyFormatMessage(e.ErrorCode), TEXT("7-Zip"), MB_ICONERROR);
return E_FAIL;
}
catch(...)
{
MyMessageBoxError(0, L"Some error");
return E_FAIL;
}
}
STDMETHODIMP CThreadBenchmark::SetRatioInfo(
const UInt64 *inSize, const UInt64 *outSize)
{
NSynchronization::CCriticalSectionLock lock(SyncInfo->CS);
if (SyncInfo->Changed || SyncInfo->WasPaused() || SyncInfo->WasStopped())
return E_ABORT;
CProgressInfo ci;
ci.InSize = *inSize;
ci.OutSize = *outSize;
ci.Time = ::GetTimeCount() - _startTime;
SyncInfo->ProcessedSize = *inSize;
UInt64 deltaTime = ci.Time - SyncInfo->CompressingInfoPrev.Time;
if (deltaTime >= GetFreq())
{
SyncInfo->CompressingInfoTemp.Time = deltaTime;
SyncInfo->CompressingInfoTemp.InSize = ci.InSize - SyncInfo->CompressingInfoPrev.InSize;
SyncInfo->CompressingInfoTemp.OutSize = ci.InSize - SyncInfo->CompressingInfoPrev.OutSize;
SyncInfo->CompressingInfoPrev = ci;
}
if (*inSize >= _approvedStart && SyncInfo->ApprovedInfo.InSize == 0)
SyncInfo->ApprovedInfo = ci;
return S_OK;
}
static bool GetCoderPath(UString &path)
{
if (!GetProgramFolderPath(path))
return false;
path += L"Codecs\\LZMA.dll";
return true;
}
typedef UInt32 (WINAPI *GetMethodPropertyFunc)(
UInt32 index, PROPID propID, PROPVARIANT *value);
static bool LoadCoder(
const UString &filePath,
NWindows::NDLL::CLibrary &library,
CLSID &encoder, CLSID &decoder)
{
if (!library.Load(filePath))
return false;
GetMethodPropertyFunc getMethodProperty = (GetMethodPropertyFunc)
library.GetProcAddress("GetMethodProperty");
if (getMethodProperty == NULL)
return false;
NWindows::NCOM::CPropVariant propVariant;
if (getMethodProperty (0, NMethodPropID::kEncoder, &propVariant) != S_OK)
return false;
if (propVariant.vt != VT_BSTR)
return false;
encoder = *(const GUID *)propVariant.bstrVal;
propVariant.Clear();
if (getMethodProperty (0, NMethodPropID::kDecoder, &propVariant) != S_OK)
return false;
if (propVariant.vt != VT_BSTR)
return false;
decoder = *(const GUID *)propVariant.bstrVal;
propVariant.Clear();
return true;
}
void Benchmark(HWND hwnd)
{
UString path;
if (!GetCoderPath(path))
{
MyMessageBoxError(hwnd, L"Can't find LZMA.dll");
return;
}
CLSID encoder;
CLSID decoder;
CThreadBenchmark benchmarker;
if (!LoadCoder(path, benchmarker.Library, encoder, decoder))
{
MyMessageBoxError(hwnd, L"Can't load LZMA.dll");
return;
}
CreateObjectPointer createObject = (CreateObjectPointer)
benchmarker.Library.GetProcAddress("CreateObject");
if (createObject == NULL)
{
MyMessageBoxError(hwnd, L"Incorrect LZMA.dll");
return;
}
if (createObject(&encoder, &IID_ICompressCoder, (void **)&benchmarker.Encoder) != S_OK)
{
MyMessageBoxError(hwnd, L"Can't create codec");
return;
}
if (createObject(&decoder, &IID_ICompressCoder, (void **)&benchmarker.Decoder) != S_OK)
{
MyMessageBoxError(hwnd, L"Can't create codec");
return;
}
CBenchmarkDialog benchmarkDialog;
benchmarker.SyncInfo = &benchmarkDialog._syncInfo;
CThread thread;
if (!thread.Create(CThreadBenchmark::MyThreadFunction, &benchmarker))
{
MyMessageBoxError(hwnd, L"error");
return;
}
benchmarkDialog.Create(hwnd);
WaitForSingleObject(thread, INFINITE);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -