| // 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; |
| } |