1370b324cSopenharmony_ci// LzmaBench.cs 2370b324cSopenharmony_ci 3370b324cSopenharmony_ciusing System; 4370b324cSopenharmony_ciusing System.IO; 5370b324cSopenharmony_ci 6370b324cSopenharmony_cinamespace SevenZip 7370b324cSopenharmony_ci{ 8370b324cSopenharmony_ci /// <summary> 9370b324cSopenharmony_ci /// LZMA Benchmark 10370b324cSopenharmony_ci /// </summary> 11370b324cSopenharmony_ci internal abstract class LzmaBench 12370b324cSopenharmony_ci { 13370b324cSopenharmony_ci const UInt32 kAdditionalSize = (6 << 20); 14370b324cSopenharmony_ci const UInt32 kCompressedAdditionalSize = (1 << 10); 15370b324cSopenharmony_ci const UInt32 kMaxLzmaPropSize = 10; 16370b324cSopenharmony_ci 17370b324cSopenharmony_ci class CRandomGenerator 18370b324cSopenharmony_ci { 19370b324cSopenharmony_ci UInt32 A1; 20370b324cSopenharmony_ci UInt32 A2; 21370b324cSopenharmony_ci public CRandomGenerator() { Init(); } 22370b324cSopenharmony_ci public void Init() { A1 = 362436069; A2 = 521288629; } 23370b324cSopenharmony_ci public UInt32 GetRnd() 24370b324cSopenharmony_ci { 25370b324cSopenharmony_ci return 26370b324cSopenharmony_ci ((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^ 27370b324cSopenharmony_ci ((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16))); 28370b324cSopenharmony_ci } 29370b324cSopenharmony_ci }; 30370b324cSopenharmony_ci 31370b324cSopenharmony_ci class CBitRandomGenerator 32370b324cSopenharmony_ci { 33370b324cSopenharmony_ci CRandomGenerator RG = new CRandomGenerator(); 34370b324cSopenharmony_ci UInt32 Value; 35370b324cSopenharmony_ci int NumBits; 36370b324cSopenharmony_ci public void Init() 37370b324cSopenharmony_ci { 38370b324cSopenharmony_ci Value = 0; 39370b324cSopenharmony_ci NumBits = 0; 40370b324cSopenharmony_ci } 41370b324cSopenharmony_ci public UInt32 GetRnd(int numBits) 42370b324cSopenharmony_ci { 43370b324cSopenharmony_ci UInt32 result; 44370b324cSopenharmony_ci if (NumBits > numBits) 45370b324cSopenharmony_ci { 46370b324cSopenharmony_ci result = Value & (((UInt32)1 << numBits) - 1); 47370b324cSopenharmony_ci Value >>= numBits; 48370b324cSopenharmony_ci NumBits -= numBits; 49370b324cSopenharmony_ci return result; 50370b324cSopenharmony_ci } 51370b324cSopenharmony_ci numBits -= NumBits; 52370b324cSopenharmony_ci result = (Value << numBits); 53370b324cSopenharmony_ci Value = RG.GetRnd(); 54370b324cSopenharmony_ci result |= Value & (((UInt32)1 << numBits) - 1); 55370b324cSopenharmony_ci Value >>= numBits; 56370b324cSopenharmony_ci NumBits = 32 - numBits; 57370b324cSopenharmony_ci return result; 58370b324cSopenharmony_ci } 59370b324cSopenharmony_ci }; 60370b324cSopenharmony_ci 61370b324cSopenharmony_ci class CBenchRandomGenerator 62370b324cSopenharmony_ci { 63370b324cSopenharmony_ci CBitRandomGenerator RG = new CBitRandomGenerator(); 64370b324cSopenharmony_ci UInt32 Pos; 65370b324cSopenharmony_ci UInt32 Rep0; 66370b324cSopenharmony_ci 67370b324cSopenharmony_ci public UInt32 BufferSize; 68370b324cSopenharmony_ci public Byte[] Buffer = null; 69370b324cSopenharmony_ci 70370b324cSopenharmony_ci public CBenchRandomGenerator() { } 71370b324cSopenharmony_ci 72370b324cSopenharmony_ci public void Set(UInt32 bufferSize) 73370b324cSopenharmony_ci { 74370b324cSopenharmony_ci Buffer = new Byte[bufferSize]; 75370b324cSopenharmony_ci Pos = 0; 76370b324cSopenharmony_ci BufferSize = bufferSize; 77370b324cSopenharmony_ci } 78370b324cSopenharmony_ci UInt32 GetRndBit() { return RG.GetRnd(1); } 79370b324cSopenharmony_ci UInt32 GetLogRandBits(int numBits) 80370b324cSopenharmony_ci { 81370b324cSopenharmony_ci UInt32 len = RG.GetRnd(numBits); 82370b324cSopenharmony_ci return RG.GetRnd((int)len); 83370b324cSopenharmony_ci } 84370b324cSopenharmony_ci UInt32 GetOffset() 85370b324cSopenharmony_ci { 86370b324cSopenharmony_ci if (GetRndBit() == 0) 87370b324cSopenharmony_ci return GetLogRandBits(4); 88370b324cSopenharmony_ci return (GetLogRandBits(4) << 10) | RG.GetRnd(10); 89370b324cSopenharmony_ci } 90370b324cSopenharmony_ci UInt32 GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); } 91370b324cSopenharmony_ci UInt32 GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); } 92370b324cSopenharmony_ci public void Generate() 93370b324cSopenharmony_ci { 94370b324cSopenharmony_ci RG.Init(); 95370b324cSopenharmony_ci Rep0 = 1; 96370b324cSopenharmony_ci while (Pos < BufferSize) 97370b324cSopenharmony_ci { 98370b324cSopenharmony_ci if (GetRndBit() == 0 || Pos < 1) 99370b324cSopenharmony_ci Buffer[Pos++] = (Byte)RG.GetRnd(8); 100370b324cSopenharmony_ci else 101370b324cSopenharmony_ci { 102370b324cSopenharmony_ci UInt32 len; 103370b324cSopenharmony_ci if (RG.GetRnd(3) == 0) 104370b324cSopenharmony_ci len = 1 + GetLen1(); 105370b324cSopenharmony_ci else 106370b324cSopenharmony_ci { 107370b324cSopenharmony_ci do 108370b324cSopenharmony_ci Rep0 = GetOffset(); 109370b324cSopenharmony_ci while (Rep0 >= Pos); 110370b324cSopenharmony_ci Rep0++; 111370b324cSopenharmony_ci len = 2 + GetLen2(); 112370b324cSopenharmony_ci } 113370b324cSopenharmony_ci for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++) 114370b324cSopenharmony_ci Buffer[Pos] = Buffer[Pos - Rep0]; 115370b324cSopenharmony_ci } 116370b324cSopenharmony_ci } 117370b324cSopenharmony_ci } 118370b324cSopenharmony_ci }; 119370b324cSopenharmony_ci 120370b324cSopenharmony_ci class CrcOutStream : System.IO.Stream 121370b324cSopenharmony_ci { 122370b324cSopenharmony_ci public CRC CRC = new CRC(); 123370b324cSopenharmony_ci public void Init() { CRC.Init(); } 124370b324cSopenharmony_ci public UInt32 GetDigest() { return CRC.GetDigest(); } 125370b324cSopenharmony_ci 126370b324cSopenharmony_ci public override bool CanRead { get { return false; } } 127370b324cSopenharmony_ci public override bool CanSeek { get { return false; } } 128370b324cSopenharmony_ci public override bool CanWrite { get { return true; } } 129370b324cSopenharmony_ci public override Int64 Length { get { return 0; } } 130370b324cSopenharmony_ci public override Int64 Position { get { return 0; } set { } } 131370b324cSopenharmony_ci public override void Flush() { } 132370b324cSopenharmony_ci public override long Seek(long offset, SeekOrigin origin) { return 0; } 133370b324cSopenharmony_ci public override void SetLength(long value) { } 134370b324cSopenharmony_ci public override int Read(byte[] buffer, int offset, int count) { return 0; } 135370b324cSopenharmony_ci 136370b324cSopenharmony_ci public override void WriteByte(byte b) 137370b324cSopenharmony_ci { 138370b324cSopenharmony_ci CRC.UpdateByte(b); 139370b324cSopenharmony_ci } 140370b324cSopenharmony_ci public override void Write(byte[] buffer, int offset, int count) 141370b324cSopenharmony_ci { 142370b324cSopenharmony_ci CRC.Update(buffer, (uint)offset, (uint)count); 143370b324cSopenharmony_ci } 144370b324cSopenharmony_ci }; 145370b324cSopenharmony_ci 146370b324cSopenharmony_ci class CProgressInfo : ICodeProgress 147370b324cSopenharmony_ci { 148370b324cSopenharmony_ci public Int64 ApprovedStart; 149370b324cSopenharmony_ci public Int64 InSize; 150370b324cSopenharmony_ci public System.DateTime Time; 151370b324cSopenharmony_ci public void Init() { InSize = 0; } 152370b324cSopenharmony_ci public void SetProgress(Int64 inSize, Int64 outSize) 153370b324cSopenharmony_ci { 154370b324cSopenharmony_ci if (inSize >= ApprovedStart && InSize == 0) 155370b324cSopenharmony_ci { 156370b324cSopenharmony_ci Time = DateTime.UtcNow; 157370b324cSopenharmony_ci InSize = inSize; 158370b324cSopenharmony_ci } 159370b324cSopenharmony_ci } 160370b324cSopenharmony_ci } 161370b324cSopenharmony_ci const int kSubBits = 8; 162370b324cSopenharmony_ci 163370b324cSopenharmony_ci static UInt32 GetLogSize(UInt32 size) 164370b324cSopenharmony_ci { 165370b324cSopenharmony_ci for (int i = kSubBits; i < 32; i++) 166370b324cSopenharmony_ci for (UInt32 j = 0; j < (1 << kSubBits); j++) 167370b324cSopenharmony_ci if (size <= (((UInt32)1) << i) + (j << (i - kSubBits))) 168370b324cSopenharmony_ci return (UInt32)(i << kSubBits) + j; 169370b324cSopenharmony_ci return (32 << kSubBits); 170370b324cSopenharmony_ci } 171370b324cSopenharmony_ci 172370b324cSopenharmony_ci static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime) 173370b324cSopenharmony_ci { 174370b324cSopenharmony_ci UInt64 freq = TimeSpan.TicksPerSecond; 175370b324cSopenharmony_ci UInt64 elTime = elapsedTime; 176370b324cSopenharmony_ci while (freq > 1000000) 177370b324cSopenharmony_ci { 178370b324cSopenharmony_ci freq >>= 1; 179370b324cSopenharmony_ci elTime >>= 1; 180370b324cSopenharmony_ci } 181370b324cSopenharmony_ci if (elTime == 0) 182370b324cSopenharmony_ci elTime = 1; 183370b324cSopenharmony_ci return value * freq / elTime; 184370b324cSopenharmony_ci } 185370b324cSopenharmony_ci 186370b324cSopenharmony_ci static UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size) 187370b324cSopenharmony_ci { 188370b324cSopenharmony_ci UInt64 t = GetLogSize(dictionarySize) - (18 << kSubBits); 189370b324cSopenharmony_ci UInt64 numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits)); 190370b324cSopenharmony_ci UInt64 numCommands = (UInt64)(size) * numCommandsForOne; 191370b324cSopenharmony_ci return MyMultDiv64(numCommands, elapsedTime); 192370b324cSopenharmony_ci } 193370b324cSopenharmony_ci 194370b324cSopenharmony_ci static UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 outSize, UInt64 inSize) 195370b324cSopenharmony_ci { 196370b324cSopenharmony_ci UInt64 numCommands = inSize * 220 + outSize * 20; 197370b324cSopenharmony_ci return MyMultDiv64(numCommands, elapsedTime); 198370b324cSopenharmony_ci } 199370b324cSopenharmony_ci 200370b324cSopenharmony_ci static UInt64 GetTotalRating( 201370b324cSopenharmony_ci UInt32 dictionarySize, 202370b324cSopenharmony_ci UInt64 elapsedTimeEn, UInt64 sizeEn, 203370b324cSopenharmony_ci UInt64 elapsedTimeDe, 204370b324cSopenharmony_ci UInt64 inSizeDe, UInt64 outSizeDe) 205370b324cSopenharmony_ci { 206370b324cSopenharmony_ci return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) + 207370b324cSopenharmony_ci GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; 208370b324cSopenharmony_ci } 209370b324cSopenharmony_ci 210370b324cSopenharmony_ci static void PrintValue(UInt64 v) 211370b324cSopenharmony_ci { 212370b324cSopenharmony_ci string s = v.ToString(); 213370b324cSopenharmony_ci for (int i = 0; i + s.Length < 6; i++) 214370b324cSopenharmony_ci System.Console.Write(" "); 215370b324cSopenharmony_ci System.Console.Write(s); 216370b324cSopenharmony_ci } 217370b324cSopenharmony_ci 218370b324cSopenharmony_ci static void PrintRating(UInt64 rating) 219370b324cSopenharmony_ci { 220370b324cSopenharmony_ci PrintValue(rating / 1000000); 221370b324cSopenharmony_ci System.Console.Write(" MIPS"); 222370b324cSopenharmony_ci } 223370b324cSopenharmony_ci 224370b324cSopenharmony_ci static void PrintResults( 225370b324cSopenharmony_ci UInt32 dictionarySize, 226370b324cSopenharmony_ci UInt64 elapsedTime, 227370b324cSopenharmony_ci UInt64 size, 228370b324cSopenharmony_ci bool decompressMode, UInt64 secondSize) 229370b324cSopenharmony_ci { 230370b324cSopenharmony_ci UInt64 speed = MyMultDiv64(size, elapsedTime); 231370b324cSopenharmony_ci PrintValue(speed / 1024); 232370b324cSopenharmony_ci System.Console.Write(" KB/s "); 233370b324cSopenharmony_ci UInt64 rating; 234370b324cSopenharmony_ci if (decompressMode) 235370b324cSopenharmony_ci rating = GetDecompressRating(elapsedTime, size, secondSize); 236370b324cSopenharmony_ci else 237370b324cSopenharmony_ci rating = GetCompressRating(dictionarySize, elapsedTime, size); 238370b324cSopenharmony_ci PrintRating(rating); 239370b324cSopenharmony_ci } 240370b324cSopenharmony_ci 241370b324cSopenharmony_ci static public int LzmaBenchmark(Int32 numIterations, UInt32 dictionarySize) 242370b324cSopenharmony_ci { 243370b324cSopenharmony_ci if (numIterations <= 0) 244370b324cSopenharmony_ci return 0; 245370b324cSopenharmony_ci if (dictionarySize < (1 << 18)) 246370b324cSopenharmony_ci { 247370b324cSopenharmony_ci System.Console.WriteLine("\nError: dictionary size for benchmark must be >= 19 (512 KB)"); 248370b324cSopenharmony_ci return 1; 249370b324cSopenharmony_ci } 250370b324cSopenharmony_ci System.Console.Write("\n Compressing Decompressing\n\n"); 251370b324cSopenharmony_ci 252370b324cSopenharmony_ci Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder(); 253370b324cSopenharmony_ci Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder(); 254370b324cSopenharmony_ci 255370b324cSopenharmony_ci 256370b324cSopenharmony_ci CoderPropID[] propIDs = 257370b324cSopenharmony_ci { 258370b324cSopenharmony_ci CoderPropID.DictionarySize, 259370b324cSopenharmony_ci }; 260370b324cSopenharmony_ci object[] properties = 261370b324cSopenharmony_ci { 262370b324cSopenharmony_ci (Int32)(dictionarySize), 263370b324cSopenharmony_ci }; 264370b324cSopenharmony_ci 265370b324cSopenharmony_ci UInt32 kBufferSize = dictionarySize + kAdditionalSize; 266370b324cSopenharmony_ci UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; 267370b324cSopenharmony_ci 268370b324cSopenharmony_ci encoder.SetCoderProperties(propIDs, properties); 269370b324cSopenharmony_ci System.IO.MemoryStream propStream = new System.IO.MemoryStream(); 270370b324cSopenharmony_ci encoder.WriteCoderProperties(propStream); 271370b324cSopenharmony_ci byte[] propArray = propStream.ToArray(); 272370b324cSopenharmony_ci 273370b324cSopenharmony_ci CBenchRandomGenerator rg = new CBenchRandomGenerator(); 274370b324cSopenharmony_ci 275370b324cSopenharmony_ci rg.Set(kBufferSize); 276370b324cSopenharmony_ci rg.Generate(); 277370b324cSopenharmony_ci CRC crc = new CRC(); 278370b324cSopenharmony_ci crc.Init(); 279370b324cSopenharmony_ci crc.Update(rg.Buffer, 0, rg.BufferSize); 280370b324cSopenharmony_ci 281370b324cSopenharmony_ci CProgressInfo progressInfo = new CProgressInfo(); 282370b324cSopenharmony_ci progressInfo.ApprovedStart = dictionarySize; 283370b324cSopenharmony_ci 284370b324cSopenharmony_ci UInt64 totalBenchSize = 0; 285370b324cSopenharmony_ci UInt64 totalEncodeTime = 0; 286370b324cSopenharmony_ci UInt64 totalDecodeTime = 0; 287370b324cSopenharmony_ci UInt64 totalCompressedSize = 0; 288370b324cSopenharmony_ci 289370b324cSopenharmony_ci MemoryStream inStream = new MemoryStream(rg.Buffer, 0, (int)rg.BufferSize); 290370b324cSopenharmony_ci MemoryStream compressedStream = new MemoryStream((int)kCompressedBufferSize); 291370b324cSopenharmony_ci CrcOutStream crcOutStream = new CrcOutStream(); 292370b324cSopenharmony_ci for (Int32 i = 0; i < numIterations; i++) 293370b324cSopenharmony_ci { 294370b324cSopenharmony_ci progressInfo.Init(); 295370b324cSopenharmony_ci inStream.Seek(0, SeekOrigin.Begin); 296370b324cSopenharmony_ci compressedStream.Seek(0, SeekOrigin.Begin); 297370b324cSopenharmony_ci encoder.Code(inStream, compressedStream, -1, -1, progressInfo); 298370b324cSopenharmony_ci TimeSpan sp2 = DateTime.UtcNow - progressInfo.Time; 299370b324cSopenharmony_ci UInt64 encodeTime = (UInt64)sp2.Ticks; 300370b324cSopenharmony_ci 301370b324cSopenharmony_ci long compressedSize = compressedStream.Position; 302370b324cSopenharmony_ci if (progressInfo.InSize == 0) 303370b324cSopenharmony_ci throw (new Exception("Internal ERROR 1282")); 304370b324cSopenharmony_ci 305370b324cSopenharmony_ci UInt64 decodeTime = 0; 306370b324cSopenharmony_ci for (int j = 0; j < 2; j++) 307370b324cSopenharmony_ci { 308370b324cSopenharmony_ci compressedStream.Seek(0, SeekOrigin.Begin); 309370b324cSopenharmony_ci crcOutStream.Init(); 310370b324cSopenharmony_ci 311370b324cSopenharmony_ci decoder.SetDecoderProperties(propArray); 312370b324cSopenharmony_ci UInt64 outSize = kBufferSize; 313370b324cSopenharmony_ci System.DateTime startTime = DateTime.UtcNow; 314370b324cSopenharmony_ci decoder.Code(compressedStream, crcOutStream, 0, (Int64)outSize, null); 315370b324cSopenharmony_ci TimeSpan sp = (DateTime.UtcNow - startTime); 316370b324cSopenharmony_ci decodeTime = (ulong)sp.Ticks; 317370b324cSopenharmony_ci if (crcOutStream.GetDigest() != crc.GetDigest()) 318370b324cSopenharmony_ci throw (new Exception("CRC Error")); 319370b324cSopenharmony_ci } 320370b324cSopenharmony_ci UInt64 benchSize = kBufferSize - (UInt64)progressInfo.InSize; 321370b324cSopenharmony_ci PrintResults(dictionarySize, encodeTime, benchSize, false, 0); 322370b324cSopenharmony_ci System.Console.Write(" "); 323370b324cSopenharmony_ci PrintResults(dictionarySize, decodeTime, kBufferSize, true, (ulong)compressedSize); 324370b324cSopenharmony_ci System.Console.WriteLine(); 325370b324cSopenharmony_ci 326370b324cSopenharmony_ci totalBenchSize += benchSize; 327370b324cSopenharmony_ci totalEncodeTime += encodeTime; 328370b324cSopenharmony_ci totalDecodeTime += decodeTime; 329370b324cSopenharmony_ci totalCompressedSize += (ulong)compressedSize; 330370b324cSopenharmony_ci } 331370b324cSopenharmony_ci System.Console.WriteLine("---------------------------------------------------"); 332370b324cSopenharmony_ci PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0); 333370b324cSopenharmony_ci System.Console.Write(" "); 334370b324cSopenharmony_ci PrintResults(dictionarySize, totalDecodeTime, 335370b324cSopenharmony_ci kBufferSize * (UInt64)numIterations, true, totalCompressedSize); 336370b324cSopenharmony_ci System.Console.WriteLine(" Average"); 337370b324cSopenharmony_ci return 0; 338370b324cSopenharmony_ci } 339370b324cSopenharmony_ci } 340370b324cSopenharmony_ci} 341