Annotation of elwix/tools/oldlzma/SRC/7zip/Compress/LZMA_Alone/LzmaBench.cpp, revision 1.1

1.1     ! misho       1: // LzmaBench.cpp
        !             2: 
        !             3: #include "StdAfx.h"
        !             4: 
        !             5: #include "LzmaBench.h"
        !             6: 
        !             7: #ifndef _WIN32
        !             8: #include <time.h>
        !             9: #endif
        !            10: 
        !            11: #include "../../../Common/CRC.h"
        !            12: #include "../LZMA/LZMADecoder.h"
        !            13: #include "../LZMA/LZMAEncoder.h"
        !            14: 
        !            15: static const UInt32 kAdditionalSize = 
        !            16: #ifdef _WIN32_WCE
        !            17: (1 << 20);
        !            18: #else
        !            19: (6 << 20);
        !            20: #endif
        !            21: 
        !            22: static const UInt32 kCompressedAdditionalSize = (1 << 10);
        !            23: static const UInt32 kMaxLzmaPropSize = 10;
        !            24: 
        !            25: class CRandomGenerator
        !            26: {
        !            27:   UInt32 A1;
        !            28:   UInt32 A2;
        !            29: public:
        !            30:   CRandomGenerator() { Init(); }
        !            31:   void Init() { A1 = 362436069; A2 = 521288629;}
        !            32:   UInt32 GetRnd() 
        !            33:   {
        !            34:     return 
        !            35:       ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^
        !            36:       ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)) );
        !            37:   }
        !            38: };
        !            39: 
        !            40: class CBitRandomGenerator
        !            41: {
        !            42:   CRandomGenerator RG;
        !            43:   UInt32 Value;
        !            44:   int NumBits;
        !            45: public:
        !            46:   void Init()
        !            47:   {
        !            48:     Value = 0;
        !            49:     NumBits = 0;
        !            50:   }
        !            51:   UInt32 GetRnd(int numBits) 
        !            52:   {
        !            53:     if (NumBits > numBits)
        !            54:     {
        !            55:       UInt32 result = Value & ((1 << numBits) - 1);
        !            56:       Value >>= numBits;
        !            57:       NumBits -= numBits;
        !            58:       return result;
        !            59:     }
        !            60:     numBits -= NumBits;
        !            61:     UInt32 result = (Value << numBits);
        !            62:     Value = RG.GetRnd();
        !            63:     result |= Value & ((1 << numBits) - 1);
        !            64:     Value >>= numBits;
        !            65:     NumBits = 32 - numBits;
        !            66:     return result;
        !            67:   }
        !            68: };
        !            69: 
        !            70: class CBenchRandomGenerator
        !            71: {
        !            72:   CBitRandomGenerator RG;
        !            73:   UInt32 Pos;
        !            74: public:
        !            75:   UInt32 BufferSize;
        !            76:   Byte *Buffer;
        !            77:   CBenchRandomGenerator(): Buffer(0) {} 
        !            78:   ~CBenchRandomGenerator() { delete []Buffer; }
        !            79:   void Init() { RG.Init(); }
        !            80:   void Set(UInt32 bufferSize) 
        !            81:   {
        !            82:     delete []Buffer;
        !            83:     Buffer = 0;
        !            84:     Buffer = new Byte[bufferSize];
        !            85:     Pos = 0;
        !            86:     BufferSize = bufferSize;
        !            87:   }
        !            88:   UInt32 GetRndBit() { return RG.GetRnd(1); }
        !            89:   /*
        !            90:   UInt32 GetLogRand(int maxLen)
        !            91:   {
        !            92:     UInt32 len = GetRnd() % (maxLen + 1);
        !            93:     return GetRnd() & ((1 << len) - 1);
        !            94:   }
        !            95:   */
        !            96:   UInt32 GetLogRandBits(int numBits)
        !            97:   {
        !            98:     UInt32 len = RG.GetRnd(numBits);
        !            99:     return RG.GetRnd(len);
        !           100:   }
        !           101:   UInt32 GetOffset()
        !           102:   {
        !           103:     if (GetRndBit() == 0)
        !           104:       return GetLogRandBits(4);
        !           105:     return (GetLogRandBits(4) << 10) | RG.GetRnd(10);
        !           106:   }
        !           107:   UInt32 GetLen()
        !           108:   {
        !           109:     if (GetRndBit() == 0)
        !           110:       return RG.GetRnd(2);
        !           111:     if (GetRndBit() == 0)
        !           112:       return 4 + RG.GetRnd(3);
        !           113:     return 12 + RG.GetRnd(4);
        !           114:   }
        !           115:   void Generate()
        !           116:   {
        !           117:     while(Pos < BufferSize)
        !           118:     {
        !           119:       if (GetRndBit() == 0 || Pos < 1)
        !           120:         Buffer[Pos++] = Byte(RG.GetRnd(8));
        !           121:       else
        !           122:       {
        !           123:         UInt32 offset = GetOffset();
        !           124:         while (offset >= Pos)
        !           125:           offset >>= 1;
        !           126:         offset += 1;
        !           127:         UInt32 len = 2 + GetLen();
        !           128:         for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++)
        !           129:           Buffer[Pos] = Buffer[Pos - offset];
        !           130:       }
        !           131:     }
        !           132:   }
        !           133: };
        !           134: 
        !           135: class CBenchmarkInStream: 
        !           136:   public ISequentialInStream,
        !           137:   public CMyUnknownImp
        !           138: {
        !           139:   const Byte *Data;
        !           140:   UInt32 Pos;
        !           141:   UInt32 Size;
        !           142: public:
        !           143:   MY_UNKNOWN_IMP
        !           144:   void Init(const Byte *data, UInt32 size)
        !           145:   {
        !           146:     Data = data;
        !           147:     Size = size;
        !           148:     Pos = 0;
        !           149:   }
        !           150:   STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
        !           151:   STDMETHOD(ReadPart)(void *data, UInt32 size, UInt32 *processedSize);
        !           152: };
        !           153: 
        !           154: STDMETHODIMP CBenchmarkInStream::Read(void *data, UInt32 size, UInt32 *processedSize)
        !           155: {
        !           156:   UInt32 remain = Size - Pos;
        !           157:   if (size > remain)
        !           158:     size = remain;
        !           159:   for (UInt32 i = 0; i < size; i++)
        !           160:   {
        !           161:     ((Byte *)data)[i] = Data[Pos + i];
        !           162:   }
        !           163:   Pos += size;
        !           164:   if(processedSize != NULL)
        !           165:     *processedSize = size;
        !           166:   return S_OK;
        !           167: }
        !           168:   
        !           169: STDMETHODIMP CBenchmarkInStream::ReadPart(void *data, UInt32 size, UInt32 *processedSize)
        !           170: {
        !           171:   return Read(data, size, processedSize);
        !           172: }
        !           173: 
        !           174: class CBenchmarkOutStream: 
        !           175:   public ISequentialOutStream,
        !           176:   public CMyUnknownImp
        !           177: {
        !           178:   UInt32 BufferSize;
        !           179:   FILE *_f;
        !           180: public:
        !           181:   UInt32 Pos;
        !           182:   Byte *Buffer;
        !           183:   CBenchmarkOutStream(): _f(0), Buffer(0) {} 
        !           184:   virtual ~CBenchmarkOutStream() { delete []Buffer; }
        !           185:   void Init(FILE *f, UInt32 bufferSize) 
        !           186:   {
        !           187:     delete []Buffer;
        !           188:     Buffer = 0;
        !           189:     Buffer = new Byte[bufferSize];
        !           190:     Pos = 0;
        !           191:     BufferSize = bufferSize;
        !           192:     _f = f;
        !           193:   }
        !           194:   MY_UNKNOWN_IMP
        !           195:   STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
        !           196:   STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize);
        !           197: };
        !           198: 
        !           199: STDMETHODIMP CBenchmarkOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
        !           200: {
        !           201:   UInt32 i;
        !           202:   for (i = 0; i < size && Pos < BufferSize; i++)
        !           203:     Buffer[Pos++] = ((const Byte *)data)[i];
        !           204:   if(processedSize != NULL)
        !           205:     *processedSize = i;
        !           206:   if (i != size)
        !           207:   {
        !           208:     fprintf(_f, "\nERROR: Buffer is full\n");
        !           209:     return E_FAIL;
        !           210:   }
        !           211:   return S_OK;
        !           212: }
        !           213:   
        !           214: STDMETHODIMP CBenchmarkOutStream::WritePart(const void *data, UInt32 size, UInt32 *processedSize)
        !           215: {
        !           216:   return Write(data, size, processedSize);
        !           217: }
        !           218: 
        !           219: class CCrcOutStream: 
        !           220:   public ISequentialOutStream,
        !           221:   public CMyUnknownImp
        !           222: {
        !           223: public:
        !           224:   CCRC CRC;
        !           225:   MY_UNKNOWN_IMP
        !           226:   void Init() { CRC.Init(); }
        !           227:   STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
        !           228:   STDMETHOD(WritePart)(const void *data, UInt32 size, UInt32 *processedSize);
        !           229: };
        !           230: 
        !           231: STDMETHODIMP CCrcOutStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
        !           232: {
        !           233:   CRC.Update(data, size);
        !           234:   if(processedSize != NULL)
        !           235:     *processedSize = size;
        !           236:   return S_OK;
        !           237: }
        !           238:   
        !           239: STDMETHODIMP CCrcOutStream::WritePart(const void *data, UInt32 size, UInt32 *processedSize)
        !           240: {
        !           241:   return Write(data, size, processedSize);
        !           242: }
        !           243: 
        !           244: static UInt64 GetTimeCount()
        !           245: {
        !           246:   #ifdef _WIN32
        !           247:   LARGE_INTEGER value;
        !           248:   if (::QueryPerformanceCounter(&value))
        !           249:     return value.QuadPart;
        !           250:   return GetTickCount();
        !           251:   #else
        !           252:   return clock();
        !           253:   #endif 
        !           254: }
        !           255: 
        !           256: static UInt64 GetFreq()
        !           257: {
        !           258:   #ifdef _WIN32
        !           259:   LARGE_INTEGER value;
        !           260:   if (::QueryPerformanceFrequency(&value))
        !           261:     return value.QuadPart;
        !           262:   return 1000;
        !           263:   #else
        !           264:   return CLOCKS_PER_SEC;
        !           265:   #endif 
        !           266: }
        !           267: 
        !           268: struct CProgressInfo:
        !           269:   public ICompressProgressInfo,
        !           270:   public CMyUnknownImp
        !           271: {
        !           272:   UInt64 ApprovedStart;
        !           273:   UInt64 InSize;
        !           274:   UInt64 Time;
        !           275:   void Init()
        !           276:   {
        !           277:     InSize = 0;
        !           278:     Time = 0;
        !           279:   }
        !           280:   MY_UNKNOWN_IMP
        !           281:   STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
        !           282: };
        !           283: 
        !           284: STDMETHODIMP CProgressInfo::SetRatioInfo(const UInt64 *inSize, const UInt64 *outSize)
        !           285: {
        !           286:   if (*inSize >= ApprovedStart && InSize == 0)
        !           287:   {
        !           288:     Time = ::GetTimeCount();
        !           289:     InSize = *inSize;
        !           290:   }
        !           291:   return S_OK;
        !           292: }
        !           293: 
        !           294: static const int kSubBits = 8;
        !           295: 
        !           296: static UInt32 GetLogSize(UInt32 size)
        !           297: {
        !           298:   for (int i = kSubBits; i < 32; i++)
        !           299:     for (UInt32 j = 0; j < (1 << kSubBits); j++)
        !           300:       if (size <= (((UInt32)1) << i) + (j << (i - kSubBits)))
        !           301:         return (i << kSubBits) + j;
        !           302:   return (32 << kSubBits);
        !           303: }
        !           304: 
        !           305: static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime)
        !           306: {
        !           307:   UInt64 freq = GetFreq();
        !           308:   UInt64 elTime = elapsedTime;
        !           309:   while(freq > 1000000)
        !           310:   {
        !           311:     freq >>= 1;
        !           312:     elTime >>= 1;
        !           313:   }
        !           314:   if (elTime == 0)
        !           315:     elTime = 1;
        !           316:   return value * freq / elTime;
        !           317: }
        !           318: 
        !           319: static UInt64 GetCompressRating(UInt32 dictionarySize, bool isBT4,
        !           320:     UInt64 elapsedTime, UInt64 size)
        !           321: {
        !           322:   UInt64 numCommandsForOne;
        !           323:   if (isBT4)
        !           324:   {
        !           325:     UInt64 t = GetLogSize(dictionarySize) - (19 << kSubBits);
        !           326:     numCommandsForOne = 2000 + ((t * t * 68) >> (2 * kSubBits));
        !           327:   }
        !           328:   else
        !           329:   {
        !           330:     UInt64 t = GetLogSize(dictionarySize) - (15 << kSubBits);
        !           331:     numCommandsForOne = 1500 + ((t * t * 41) >> (2 * kSubBits));
        !           332:   }
        !           333:   UInt64 numCommands = (UInt64)(size) * numCommandsForOne;
        !           334:   return MyMultDiv64(numCommands, elapsedTime);
        !           335: }
        !           336: 
        !           337: static UInt64 GetDecompressRating(UInt64 elapsedTime, 
        !           338:     UInt64 outSize, UInt64 inSize)
        !           339: {
        !           340:   UInt64 numCommands = inSize * 250 + outSize * 21;
        !           341:   return MyMultDiv64(numCommands, elapsedTime);
        !           342: }
        !           343: 
        !           344: /*
        !           345: static UInt64 GetTotalRating(
        !           346:     UInt32 dictionarySize, 
        !           347:     bool isBT4,
        !           348:     UInt64 elapsedTimeEn, UInt64 sizeEn,
        !           349:     UInt64 elapsedTimeDe, 
        !           350:     UInt64 inSizeDe, UInt64 outSizeDe)
        !           351: {
        !           352:   return (GetCompressRating(dictionarySize, isBT4, elapsedTimeEn, sizeEn) + 
        !           353:     GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2;
        !           354: }
        !           355: */
        !           356: 
        !           357: static void PrintRating(FILE *f, UInt64 rating)
        !           358: {
        !           359:   fprintf(f, "%5d MIPS", (unsigned int)(rating / 1000000));
        !           360: }
        !           361: 
        !           362: static void PrintResults(
        !           363:     FILE *f, 
        !           364:     UInt32 dictionarySize,
        !           365:     bool isBT4,
        !           366:     UInt64 elapsedTime, 
        !           367:     UInt64 size, 
        !           368:     bool decompressMode, UInt64 secondSize)
        !           369: {
        !           370:   UInt64 speed = MyMultDiv64(size, elapsedTime);
        !           371:   fprintf(f, "%6d KB/s  ", (unsigned int)(speed / 1024));
        !           372:   UInt64 rating;
        !           373:   if (decompressMode)
        !           374:     rating = GetDecompressRating(elapsedTime, size, secondSize);
        !           375:   else
        !           376:     rating = GetCompressRating(dictionarySize, isBT4, elapsedTime, size);
        !           377:   PrintRating(f, rating);
        !           378: }
        !           379: 
        !           380: static void ThrowError(FILE *f, HRESULT result, const char *s)
        !           381: {
        !           382:   fprintf(f, "\nError: ");
        !           383:   if (result == E_ABORT)
        !           384:     fprintf(f, "User break");
        !           385:   if (result == E_OUTOFMEMORY)
        !           386:     fprintf(f, "Can not allocate memory");
        !           387:   else
        !           388:     fprintf(f, s);
        !           389:   fprintf(f, "\n");
        !           390: }
        !           391: 
        !           392: const wchar_t *bt2 = L"BT2";
        !           393: const wchar_t *bt4 = L"BT4";
        !           394: 
        !           395: int LzmaBenchmark(FILE *f, UInt32 numIterations, UInt32 dictionarySize, bool isBT4)
        !           396: {
        !           397:   if (numIterations == 0)
        !           398:     return 0;
        !           399:   if (dictionarySize < (1 << 19) && isBT4 || dictionarySize < (1 << 15))
        !           400:   {
        !           401:     fprintf(f, "\nError: dictionary size for benchmark must be >= 19 (512 KB)\n");
        !           402:     return 1;
        !           403:   }
        !           404:   fprintf(f, "\n       Compressing                Decompressing\n\n");
        !           405:   NCompress::NLZMA::CEncoder *encoderSpec = new NCompress::NLZMA::CEncoder;
        !           406:   CMyComPtr<ICompressCoder> encoder = encoderSpec;
        !           407: 
        !           408:   NCompress::NLZMA::CDecoder *decoderSpec = new NCompress::NLZMA::CDecoder;
        !           409:   CMyComPtr<ICompressCoder> decoder = decoderSpec;
        !           410: 
        !           411:   CBenchmarkOutStream *propStreamSpec = new CBenchmarkOutStream;
        !           412:   CMyComPtr<ISequentialOutStream> propStream = propStreamSpec;
        !           413:   propStreamSpec->Init(f, kMaxLzmaPropSize);
        !           414:   
        !           415:   PROPID propIDs[] = 
        !           416:   { 
        !           417:     NCoderPropID::kDictionarySize,  
        !           418:     NCoderPropID::kMatchFinder  
        !           419:   };
        !           420:   const int kNumProps = sizeof(propIDs) / sizeof(propIDs[0]);
        !           421:   PROPVARIANT properties[kNumProps];
        !           422:   properties[0].vt = VT_UI4;
        !           423:   properties[0].ulVal = UInt32(dictionarySize);
        !           424: 
        !           425:   properties[1].vt = VT_BSTR;
        !           426:   properties[1].bstrVal = isBT4 ? (BSTR)bt4: (BSTR)bt2;
        !           427: 
        !           428:   const UInt32 kBufferSize = dictionarySize + kAdditionalSize;
        !           429:   const UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize;
        !           430: 
        !           431:   if (encoderSpec->SetCoderProperties(propIDs, properties, kNumProps) != S_OK)
        !           432:   {
        !           433:     fprintf(f, "\nError: Incorrect command\n");
        !           434:     return 1;
        !           435:   }
        !           436:   encoderSpec->WriteCoderProperties(propStream);
        !           437: 
        !           438:   CBenchRandomGenerator rg;
        !           439:   rg.Init();
        !           440:   rg.Set(kBufferSize);
        !           441:   rg.Generate();
        !           442:   CCRC crc;
        !           443:   crc.Update(rg.Buffer, rg.BufferSize);
        !           444: 
        !           445:   CProgressInfo *progressInfoSpec = new CProgressInfo;
        !           446:   CMyComPtr<ICompressProgressInfo> progressInfo = progressInfoSpec;
        !           447: 
        !           448:   progressInfoSpec->ApprovedStart = dictionarySize;
        !           449: 
        !           450:   UInt64 totalBenchSize = 0;
        !           451:   UInt64 totalEncodeTime = 0;
        !           452:   UInt64 totalDecodeTime = 0;
        !           453:   UInt64 totalCompressedSize = 0;
        !           454: 
        !           455:   for (UInt32 i = 0; i < numIterations; i++)
        !           456:   {
        !           457:     progressInfoSpec->Init();
        !           458:     CBenchmarkInStream *inStreamSpec = new CBenchmarkInStream;
        !           459:     inStreamSpec->Init(rg.Buffer, rg.BufferSize);
        !           460:     CMyComPtr<ISequentialInStream> inStream = inStreamSpec;
        !           461:     CBenchmarkOutStream *outStreamSpec = new CBenchmarkOutStream;
        !           462:     outStreamSpec->Init(f, kCompressedBufferSize);
        !           463:     CMyComPtr<ISequentialOutStream> outStream = outStreamSpec;
        !           464:     HRESULT result = encoder->Code(inStream, outStream, 0, 0, progressInfo);
        !           465:     UInt64 encodeTime = ::GetTimeCount() - progressInfoSpec->Time;
        !           466:     UInt32 compressedSize = outStreamSpec->Pos;
        !           467:     if(result != S_OK)
        !           468:     {
        !           469:       ThrowError(f, result, "Encoder Error");
        !           470:       return 1;
        !           471:     }
        !           472:     if (progressInfoSpec->InSize == 0)
        !           473:     {
        !           474:       fprintf(f, "\nError: Internal ERROR 1282\n");
        !           475:       return 1;
        !           476:     }
        !           477:   
        !           478:     ///////////////////////
        !           479:     // Decompressing
        !           480:   
        !           481:     CCrcOutStream *crcOutStreamSpec = new CCrcOutStream;
        !           482:     CMyComPtr<ISequentialOutStream> crcOutStream = crcOutStreamSpec;
        !           483:     
        !           484:     UInt64 decodeTime;
        !           485:     for (int j = 0; j < 2; j++)
        !           486:     {
        !           487:       inStreamSpec->Init(outStreamSpec->Buffer, compressedSize);
        !           488:       crcOutStreamSpec->Init();
        !           489:       
        !           490:       if (decoderSpec->SetDecoderProperties2(propStreamSpec->Buffer, propStreamSpec->Pos) != S_OK)
        !           491:       {
        !           492:         fprintf(f, "\nError: Set Decoder Properties Error\n");
        !           493:         return 1;
        !           494:       }
        !           495:       UInt64 outSize = kBufferSize;
        !           496:       UInt64 startTime = ::GetTimeCount();
        !           497:       result = decoder->Code(inStream, crcOutStream, 0, &outSize, 0);
        !           498:       decodeTime = ::GetTimeCount() - startTime;
        !           499:       if(result != S_OK)
        !           500:       {
        !           501:         ThrowError(f, result, "Decode Error");
        !           502:         return 1;
        !           503:       }
        !           504:       if (crcOutStreamSpec->CRC.GetDigest() != crc.GetDigest())
        !           505:       {
        !           506:         fprintf(f, "\nError: CRC Error\n");
        !           507:         return 1;
        !           508:       }
        !           509:     }
        !           510:     UInt64 benchSize = kBufferSize - progressInfoSpec->InSize;
        !           511:     PrintResults(f, dictionarySize, isBT4, encodeTime, benchSize, false, 0);
        !           512:     fprintf(f, "     ");
        !           513:     PrintResults(f, dictionarySize, isBT4, decodeTime, kBufferSize, true, compressedSize);
        !           514:     fprintf(f, "\n");
        !           515: 
        !           516:     totalBenchSize += benchSize;
        !           517:     totalEncodeTime += encodeTime;
        !           518:     totalDecodeTime += decodeTime;
        !           519:     totalCompressedSize += compressedSize;
        !           520:   }
        !           521:   fprintf(f, "---------------------------------------------------\n");
        !           522:   PrintResults(f, dictionarySize, isBT4, totalEncodeTime, totalBenchSize, false, 0);
        !           523:   fprintf(f, "     ");
        !           524:   PrintResults(f, dictionarySize, isBT4, totalDecodeTime, 
        !           525:       kBufferSize * numIterations, true, totalCompressedSize);
        !           526:   fprintf(f, "    Average\n");
        !           527:   return 0;
        !           528: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>