312 lines
7.8 KiB
C++
312 lines
7.8 KiB
C++
// LzmaBenchCon.cpp
|
|
|
|
#include "StdAfx.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "LzmaBench.h"
|
|
#include "LzmaBenchCon.h"
|
|
#include "../../../Common/IntToString.h"
|
|
|
|
#if defined(BENCH_MT) || defined(_WIN32)
|
|
#include "../../../Windows/System.h"
|
|
#endif
|
|
|
|
#ifdef BREAK_HANDLER
|
|
#include "../../UI/Console/ConsoleClose.h"
|
|
#endif
|
|
#include "../../../Common/MyCom.h"
|
|
|
|
struct CTotalBenchRes
|
|
{
|
|
UInt64 NumIterations;
|
|
UInt64 Rating;
|
|
UInt64 Usage;
|
|
UInt64 RPU;
|
|
void Init() { NumIterations = 0; Rating = 0; Usage = 0; RPU = 0; }
|
|
void Normalize()
|
|
{
|
|
if (NumIterations == 0)
|
|
return;
|
|
Rating /= NumIterations;
|
|
Usage /= NumIterations;
|
|
RPU /= NumIterations;
|
|
NumIterations = 1;
|
|
}
|
|
void SetMid(const CTotalBenchRes &r1, const CTotalBenchRes &r2)
|
|
{
|
|
Rating = (r1.Rating + r2.Rating) / 2;
|
|
Usage = (r1.Usage + r2.Usage) / 2;
|
|
RPU = (r1.RPU + r2.RPU) / 2;
|
|
NumIterations = (r1.NumIterations + r2.NumIterations) / 2;
|
|
}
|
|
};
|
|
|
|
struct CBenchCallback: public IBenchCallback
|
|
{
|
|
CTotalBenchRes EncodeRes;
|
|
CTotalBenchRes DecodeRes;
|
|
FILE *f;
|
|
void Init() { EncodeRes.Init(); DecodeRes.Init(); }
|
|
void Normalize() { EncodeRes.Normalize(); DecodeRes.Normalize(); }
|
|
UInt32 dictionarySize;
|
|
HRESULT SetEncodeResult(const CBenchInfo &info, bool final);
|
|
HRESULT SetDecodeResult(const CBenchInfo &info, bool final);
|
|
};
|
|
|
|
static void NormalizeVals(UInt64 &v1, UInt64 &v2)
|
|
{
|
|
while (v1 > 1000000)
|
|
{
|
|
v1 >>= 1;
|
|
v2 >>= 1;
|
|
}
|
|
}
|
|
|
|
static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime, UInt64 freq)
|
|
{
|
|
UInt64 elTime = elapsedTime;
|
|
NormalizeVals(freq, elTime);
|
|
if (elTime == 0)
|
|
elTime = 1;
|
|
return value * freq / elTime;
|
|
}
|
|
|
|
static void PrintNumber(FILE *f, UInt64 value, int size)
|
|
{
|
|
char s[32];
|
|
ConvertUInt64ToString(value, s);
|
|
fprintf(f, " ");
|
|
for (int len = (int)strlen(s); len < size; len++)
|
|
fprintf(f, " ");
|
|
fprintf(f, "%s", s);
|
|
}
|
|
|
|
static void PrintRating(FILE *f, UInt64 rating)
|
|
{
|
|
PrintNumber(f, rating / 1000000, 6);
|
|
}
|
|
|
|
static void PrintResults(FILE *f, UInt64 usage, UInt64 rpu, UInt64 rating)
|
|
{
|
|
PrintNumber(f, (usage + 5000) / 10000, 5);
|
|
PrintRating(f, rpu);
|
|
PrintRating(f, rating);
|
|
}
|
|
|
|
|
|
static void PrintResults(FILE *f, const CBenchInfo &info, UInt64 rating, CTotalBenchRes &res)
|
|
{
|
|
UInt64 speed = MyMultDiv64(info.UnpackSize, info.GlobalTime, info.GlobalFreq);
|
|
PrintNumber(f, speed / 1024, 7);
|
|
UInt64 usage = GetUsage(info);
|
|
UInt64 rpu = GetRatingPerUsage(info, rating);
|
|
PrintResults(f, usage, rpu, rating);
|
|
res.NumIterations++;
|
|
res.RPU += rpu;
|
|
res.Rating += rating;
|
|
res.Usage += usage;
|
|
}
|
|
|
|
static void PrintTotals(FILE *f, const CTotalBenchRes &res)
|
|
{
|
|
fprintf(f, " ");
|
|
PrintResults(f, res.Usage, res.RPU, res.Rating);
|
|
}
|
|
|
|
|
|
HRESULT CBenchCallback::SetEncodeResult(const CBenchInfo &info, bool final)
|
|
{
|
|
#ifdef BREAK_HANDLER
|
|
if (NConsoleClose::TestBreakSignal())
|
|
return E_ABORT;
|
|
#endif
|
|
|
|
if (final)
|
|
{
|
|
UInt64 rating = GetCompressRating(dictionarySize, info.GlobalTime, info.GlobalFreq, info.UnpackSize);
|
|
PrintResults(f, info, rating, EncodeRes);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
static const char *kSep = " | ";
|
|
|
|
|
|
HRESULT CBenchCallback::SetDecodeResult(const CBenchInfo &info, bool final)
|
|
{
|
|
#ifdef BREAK_HANDLER
|
|
if (NConsoleClose::TestBreakSignal())
|
|
return E_ABORT;
|
|
#endif
|
|
if (final)
|
|
{
|
|
UInt64 rating = GetDecompressRating(info.GlobalTime, info.GlobalFreq, info.UnpackSize, info.PackSize, info.NumIterations);
|
|
fprintf(f, kSep);
|
|
CBenchInfo info2 = info;
|
|
info2.UnpackSize *= info2.NumIterations;
|
|
info2.PackSize *= info2.NumIterations;
|
|
info2.NumIterations = 1;
|
|
PrintResults(f, info2, rating, DecodeRes);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
static void PrintRequirements(FILE *f, const char *sizeString, UInt64 size, const char *threadsString, UInt32 numThreads)
|
|
{
|
|
fprintf(f, "\nRAM %s ", sizeString);
|
|
PrintNumber(f, (size >> 20), 5);
|
|
fprintf(f, " MB, # %s %3d", threadsString, (unsigned int)numThreads);
|
|
}
|
|
|
|
HRESULT LzmaBenchCon(
|
|
#ifdef EXTERNAL_LZMA
|
|
CCodecs *codecs,
|
|
#endif
|
|
FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary)
|
|
{
|
|
if (!CrcInternalTest())
|
|
return S_FALSE;
|
|
#ifdef BENCH_MT
|
|
UInt64 ramSize = NWindows::NSystem::GetRamSize(); //
|
|
UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors();
|
|
PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs);
|
|
if (numThreads == (UInt32)-1)
|
|
numThreads = numCPUs;
|
|
if (numThreads > 1)
|
|
numThreads &= ~1;
|
|
if (dictionary == (UInt32)-1)
|
|
{
|
|
int dicSizeLog;
|
|
for (dicSizeLog = 25; dicSizeLog > kBenchMinDicLogSize; dicSizeLog--)
|
|
if (GetBenchMemoryUsage(numThreads, ((UInt32)1 << dicSizeLog)) + (8 << 20) <= ramSize)
|
|
break;
|
|
dictionary = (1 << dicSizeLog);
|
|
}
|
|
#else
|
|
if (dictionary == (UInt32)-1)
|
|
dictionary = (1 << 22);
|
|
numThreads = 1;
|
|
#endif
|
|
|
|
PrintRequirements(f, "usage:", GetBenchMemoryUsage(numThreads, dictionary), "Benchmark threads: ", numThreads);
|
|
|
|
CBenchCallback callback;
|
|
callback.Init();
|
|
callback.f = f;
|
|
|
|
fprintf(f, "\n\nDict Compressing | Decompressing\n ");
|
|
int j;
|
|
for (j = 0; j < 2; j++)
|
|
{
|
|
fprintf(f, " Speed Usage R/U Rating");
|
|
if (j == 0)
|
|
fprintf(f, kSep);
|
|
}
|
|
fprintf(f, "\n ");
|
|
for (j = 0; j < 2; j++)
|
|
{
|
|
fprintf(f, " KB/s %% MIPS MIPS");
|
|
if (j == 0)
|
|
fprintf(f, kSep);
|
|
}
|
|
fprintf(f, "\n\n");
|
|
for (UInt32 i = 0; i < numIterations; i++)
|
|
{
|
|
const int kStartDicLog = 22;
|
|
int pow = (dictionary < ((UInt32)1 << kStartDicLog)) ? kBenchMinDicLogSize : kStartDicLog;
|
|
while (((UInt32)1 << pow) > dictionary)
|
|
pow--;
|
|
for (; ((UInt32)1 << pow) <= dictionary; pow++)
|
|
{
|
|
fprintf(f, "%2d:", pow);
|
|
callback.dictionarySize = (UInt32)1 << pow;
|
|
HRESULT res = LzmaBench(
|
|
#ifdef EXTERNAL_LZMA
|
|
codecs,
|
|
#endif
|
|
numThreads, callback.dictionarySize, &callback);
|
|
fprintf(f, "\n");
|
|
RINOK(res);
|
|
}
|
|
}
|
|
callback.Normalize();
|
|
fprintf(f, "----------------------------------------------------------------\nAvr:");
|
|
PrintTotals(f, callback.EncodeRes);
|
|
fprintf(f, " ");
|
|
PrintTotals(f, callback.DecodeRes);
|
|
fprintf(f, "\nTot:");
|
|
CTotalBenchRes midRes;
|
|
midRes.SetMid(callback.EncodeRes, callback.DecodeRes);
|
|
PrintTotals(f, midRes);
|
|
fprintf(f, "\n");
|
|
return S_OK;
|
|
}
|
|
|
|
struct CTempValues
|
|
{
|
|
UInt64 *Values;
|
|
CTempValues(UInt32 num) { Values = new UInt64[num]; }
|
|
~CTempValues() { delete []Values; }
|
|
};
|
|
|
|
HRESULT CrcBenchCon(FILE *f, UInt32 numIterations, UInt32 numThreads, UInt32 dictionary)
|
|
{
|
|
if (!CrcInternalTest())
|
|
return S_FALSE;
|
|
|
|
#ifdef BENCH_MT
|
|
UInt64 ramSize = NWindows::NSystem::GetRamSize();
|
|
UInt32 numCPUs = NWindows::NSystem::GetNumberOfProcessors();
|
|
PrintRequirements(f, "size: ", ramSize, "CPU hardware threads:", numCPUs);
|
|
if (numThreads == (UInt32)-1)
|
|
numThreads = numCPUs;
|
|
#else
|
|
numThreads = 1;
|
|
#endif
|
|
if (dictionary == (UInt32)-1)
|
|
dictionary = (1 << 24);
|
|
|
|
CTempValues speedTotals(numThreads);
|
|
fprintf(f, "\n\nSize");
|
|
for (UInt32 ti = 0; ti < numThreads; ti++)
|
|
{
|
|
fprintf(f, " %5d", ti + 1);
|
|
speedTotals.Values[ti] = 0;
|
|
}
|
|
fprintf(f, "\n\n");
|
|
|
|
UInt64 numSteps = 0;
|
|
for (UInt32 i = 0; i < numIterations; i++)
|
|
{
|
|
for (int pow = 10; pow < 32; pow++)
|
|
{
|
|
UInt32 bufSize = (UInt32)1 << pow;
|
|
if (bufSize > dictionary)
|
|
break;
|
|
fprintf(f, "%2d: ", pow);
|
|
UInt64 speed;
|
|
for (UInt32 ti = 0; ti < numThreads; ti++)
|
|
{
|
|
#ifdef BREAK_HANDLER
|
|
if (NConsoleClose::TestBreakSignal())
|
|
return E_ABORT;
|
|
#endif
|
|
RINOK(CrcBench(ti + 1, bufSize, speed));
|
|
PrintNumber(f, (speed >> 20), 5);
|
|
speedTotals.Values[ti] += speed;
|
|
}
|
|
fprintf(f, "\n");
|
|
numSteps++;
|
|
}
|
|
}
|
|
if (numSteps != 0)
|
|
{
|
|
fprintf(f, "\nAvg:");
|
|
for (UInt32 ti = 0; ti < numThreads; ti++)
|
|
PrintNumber(f, ((speedTotals.Values[ti] / numSteps) >> 20), 5);
|
|
fprintf(f, "\n");
|
|
}
|
|
return S_OK;
|
|
}
|