⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lzmabench.cpp

📁 sleuthit-2.09 一个磁盘的工具集
💻 CPP
字号:
// LzmaBench.cpp#include "StdAfx.h"#include "LzmaBench.h"#ifndef _WIN32#include <time.h>#endif#include "../../../Common/CRC.h"#include "../LZMA/LZMADecoder.h"#include "../LZMA/LZMAEncoder.h"static const UInt32 kAdditionalSize = #ifdef _WIN32_WCE(1 << 20);#else(6 << 20);#endifstatic const UInt32 kCompressedAdditionalSize = (1 << 10);static const UInt32 kMaxLzmaPropSize = 10;class CRandomGenerator{  UInt32 A1;  UInt32 A2;public:  CRandomGenerator() { Init(); }  void Init() { A1 = 362436069; A2 = 521288629;}  UInt32 GetRnd()   {    return       ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^      ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) );  }};class CBitRandomGenerator{  CRandomGenerator RG;  UInt32 Value;  int NumBits;public:  void Init()  {    Value = 0;    NumBits = 0;  }  UInt32 GetRnd(int numBits)   {    if (NumBits > numBits)    {      UInt32 result = Value & ((1 << numBits) - 1);      Value >>= numBits;      NumBits -= numBits;      return result;    }    numBits -= NumBits;    UInt32 result = (Value << numBits);    Value = RG.GetRnd();    result |= Value & ((1 << numBits) - 1);    Value >>= numBits;    NumBits = 32 - numBits;    return result;  }};class CBenchRandomGenerator{  CBitRandomGenerator RG;  UInt32 Pos;  UInt32 Rep0;public:  UInt32 BufferSize;  Byte *Buffer;  CBenchRandomGenerator(): Buffer(0) {}   ~CBenchRandomGenerator() { Free(); }  void Free()   {     ::MidFree(Buffer);    Buffer = 0;  }  bool Alloc(UInt32 bufferSize)   {    if (Buffer != 0 && BufferSize == bufferSize)      return true;    Free();    Buffer = (Byte *)::MidAlloc(bufferSize);    Pos = 0;    BufferSize = bufferSize;    return (Buffer != 0);  }  UInt32 GetRndBit() { return RG.GetRnd(1); }  /*  UInt32 GetLogRand(int maxLen)  {    UInt32 len = GetRnd() % (maxLen + 1);    return GetRnd() & ((1 << len) - 1);  }  */  UInt32 GetLogRandBits(int numBits)  {    UInt32 len = RG.GetRnd(numBits);    return RG.GetRnd(len);  }  UInt32 GetOffset()  {    if (GetRndBit() == 0)      return GetLogRandBits(4);    return (GetLogRandBits(4) << 10) | RG.GetRnd(10);  }  UInt32 GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); }  UInt32 GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); }  void Generate()  {    RG.Init();     Rep0 = 1;    while(Pos < BufferSize)    {      if (GetRndBit() == 0 || Pos < 1)        Buffer[Pos++] = (Byte)RG.GetRnd(8);      else      {        UInt32 len;        if (RG.GetRnd(3) == 0)          len = 1 + GetLen1();        else        {          do            Rep0 = GetOffset();          while (Rep0 >= Pos);          Rep0++;          len = 2 + GetLen2();        }        for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++)          Buffer[Pos] = Buffer[Pos - Rep0];      }    }  }};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);};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;}  class CBenchmarkOutStream:   public ISequentialOutStream,  public CMyUnknownImp{  UInt32 BufferSize;  FILE *_f;public:  UInt32 Pos;  Byte *Buffer;  CBenchmarkOutStream(): _f(0), Buffer(0) {}   virtual ~CBenchmarkOutStream() { delete []Buffer; }  void Init(FILE *f, UInt32 bufferSize)   {    delete []Buffer;    Buffer = 0;    Buffer = new Byte[bufferSize];    Pos = 0;    BufferSize = bufferSize;    _f = f;  }  MY_UNKNOWN_IMP  STDMETHOD(Write)(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)  {    fprintf(_f, "\nERROR: Buffer is full\n");    return E_FAIL;  }  return S_OK;}  class CCrcOutStream:   public ISequentialOutStream,  public CMyUnknownImp{public:  CCRC CRC;  MY_UNKNOWN_IMP  void Init() { CRC.Init(); }  STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);};STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize){  CRC.Update(data, size);  if(processedSize != NULL)    *processedSize = size;  return S_OK;}  static UInt64 GetTimeCount(){  #ifdef _WIN32  LARGE_INTEGER value;  if (::QueryPerformanceCounter(&value))    return value.QuadPart;  return GetTickCount();  #else  return clock();  #endif }static UInt64 GetFreq(){  #ifdef _WIN32  LARGE_INTEGER value;  if (::QueryPerformanceFrequency(&value))    return value.QuadPart;  return 1000;  #else  return CLOCKS_PER_SEC;  #endif }struct CProgressInfo:  public ICompressProgressInfo,  public CMyUnknownImp{  UInt64 ApprovedStart;  UInt64 InSize;  UInt64 Time;  void Init()  {    InSize = 0;    Time = 0;  }  MY_UNKNOWN_IMP  STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);};STDMETHODIMP CProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize){  if (*inSize >= ApprovedStart && InSize == 0)  {    Time = ::GetTimeCount();    InSize = *inSize;  }  return S_OK;}static const int kSubBits = 8;static UInt32 GetLogSize(UInt32 size){  for (int i = kSubBits; i < 32; i++)    for (UInt32 j = 0; j < (1 << kSubBits); j++)      if (size <= (((UInt32)1) << i) + (j << (i - kSubBits)))        return (i << kSubBits) + j;  return (32 << kSubBits);}static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime){  UInt64 freq = GetFreq();  UInt64 elTime = elapsedTime;  while(freq > 1000000)  {    freq >>= 1;    elTime >>= 1;  }  if (elTime == 0)    elTime = 1;  return value * freq / elTime;}static UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size){  UInt64 t = GetLogSize(dictionarySize) - (18 << kSubBits);  UInt64 numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits));  UInt64 numCommands = (UInt64)(size) * numCommandsForOne;  return MyMultDiv64(numCommands, elapsedTime);}static UInt64 GetDecompressRating(UInt64 elapsedTime,     UInt64 outSize, UInt64 inSize){  UInt64 numCommands = inSize * 220 + outSize * 20;  return MyMultDiv64(numCommands, elapsedTime);}/*static UInt64 GetTotalRating(    UInt32 dictionarySize,     bool isBT4,    UInt64 elapsedTimeEn, UInt64 sizeEn,    UInt64 elapsedTimeDe,     UInt64 inSizeDe, UInt64 outSizeDe){  return (GetCompressRating(dictionarySize, isBT4, elapsedTimeEn, sizeEn) +     GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2;}*/static void PrintRating(FILE *f, UInt64 rating){  fprintf(f, "%5d MIPS", (unsigned int)(rating / 1000000));}static void PrintResults(    FILE *f,     UInt32 dictionarySize,    UInt64 elapsedTime,     UInt64 size,     bool decompressMode, UInt64 secondSize){  UInt64 speed = MyMultDiv64(size, elapsedTime);  fprintf(f, "%6d KB/s  ", (unsigned int)(speed / 1024));  UInt64 rating;  if (decompressMode)    rating = GetDecompressRating(elapsedTime, size, secondSize);  else    rating = GetCompressRating(dictionarySize, elapsedTime, size);  PrintRating(f, rating);}static void ThrowError(FILE *f, HRESULT result, const char *s){  fprintf(f, "\nError: ");  if (result == E_ABORT)    fprintf(f, "User break");  if (result == E_OUTOFMEMORY)    fprintf(f, "Can not allocate memory");  else    fprintf(f, s);  fprintf(f, "\n");}const wchar_t *bt2 = L"BT2";const wchar_t *bt4 = L"BT4";int LzmaBenchmark(FILE *f, UInt32 numIterations, UInt32 dictionarySize){  if (numIterations == 0)    return 0;  if (dictionarySize < (1 << 18))  {    fprintf(f, "\nError: dictionary size for benchmark must be >= 19 (512 KB)\n");    return 1;  }  fprintf(f, "\n       Compressing                Decompressing\n\n");  NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder;  CMyComPtr<ICompressCoder> encoder = encoderSpec;  NCompress::NLZMA::CDecoder *decoderSpec = new NCompress::NLZMA::CDecoder;  CMyComPtr<ICompressCoder> decoder = decoderSpec;  CBenchmarkOutStream *propStreamSpec = new CBenchmarkOutStream;  CMyComPtr<ISequentialOutStream> propStream = propStreamSpec;  propStreamSpec->Init(f, kMaxLzmaPropSize);    PROPID propIDs[] =   {     NCoderPropID::kDictionarySize  };  const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);  PROPVARIANT properties[kNumProps];  properties[0].vt = VT_UI4;  properties[0].ulVal = UInt32(dictionarySize);  const UInt32 kBufferSize = dictionarySize + kAdditionalSize;  const UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize;  if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK)  {    fprintf(f, "\nError: Incorrect command\n");    return 1;  }  encoderSpec->WriteCoderProperties(propStream);  CBenchRandomGenerator rg;  if (!rg.Alloc(kBufferSize))  {    fprintf(f, "\nError: Can't allocate memory\n");    return 1;  }  rg.Generate();  CCRC crc;  crc.Update(rg.Buffer, rg.BufferSize);  CProgressInfo *progressInfoSpec = new CProgressInfo;  CMyComPtr<ICompressProgressInfo> progressInfo = progressInfoSpec;  progressInfoSpec->ApprovedStart = dictionarySize;  UInt64 totalBenchSize = 0;  UInt64 totalEncodeTime = 0;  UInt64 totalDecodeTime = 0;  UInt64 totalCompressedSize = 0;  for (UInt32 i = 0; i < numIterations; i++)  {    progressInfoSpec->Init();    CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream;    inStreamSpec->Init(rg.Buffer, rg.BufferSize);    CMyComPtr<ISequentialInStream> inStream = inStreamSpec;    CBenchmarkOutStream *outStreamSpec = new CBenchmarkOutStream;    outStreamSpec->Init(f, kCompressedBufferSize);    CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;    HRESULT result = encoder->Code(inStream, outStream, 0, 0, progressInfo);    UInt64 encodeTime = ::GetTimeCount() - progressInfoSpec->Time;    UInt32 compressedSize = outStreamSpec->Pos;    if(result != S_OK)    {      ThrowError(f, result, "Encoder Error");      return 1;    }    if (progressInfoSpec->InSize == 0)    {      fprintf(f, "\nError: Internal ERROR 1282\n");      return 1;    }      ///////////////////////    // Decompressing      CCrcOutStream *crcOutStreamSpec = new CCrcOutStream;    CMyComPtr<ISequentialOutStream> crcOutStream = crcOutStreamSpec;        UInt64 decodeTime;    for (int j = 0; j < 2; j++)    {      inStreamSpec->Init(outStreamSpec->Buffer, compressedSize);      crcOutStreamSpec->Init();            if (decoderSpec->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos) != S_OK)      {        fprintf(f, "\nError: Set Decoder Properties Error\n");        return 1;      }      UInt64 outSize = kBufferSize;      UInt64 startTime = ::GetTimeCount();      result = decoder->Code(inStream, crcOutStream, 0, &outSize, 0);      decodeTime = ::GetTimeCount() - startTime;      if(result != S_OK)      {        ThrowError(f, result, "Decode Error");        return 1;      }      if (crcOutStreamSpec->CRC.GetDigest() != crc.GetDigest())      {        fprintf(f, "\nError: CRC Error\n");        return 1;      }    }    UInt64 benchSize = kBufferSize - progressInfoSpec->InSize;    PrintResults(f, dictionarySize, encodeTime, benchSize, false, 0);    fprintf(f, "     ");    PrintResults(f, dictionarySize, decodeTime, kBufferSize, true, compressedSize);    fprintf(f, "\n");    totalBenchSize += benchSize;    totalEncodeTime += encodeTime;    totalDecodeTime += decodeTime;    totalCompressedSize += compressedSize;  }  fprintf(f, "---------------------------------------------------\n");  PrintResults(f, dictionarySize, totalEncodeTime, totalBenchSize, false, 0);  fprintf(f, "     ");  PrintResults(f, dictionarySize, totalDecodeTime,       kBufferSize * numIterations, true, totalCompressedSize);  fprintf(f, "    Average\n");  return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -