misc/libphysfs/lzma/CS/7zip/Compress/LzmaAlone/LzmaBench.cs
changeset 12213 bb5522e88ab2
equal deleted inserted replaced
12212:ea891871f481 12213:bb5522e88ab2
       
     1 // LzmaBench.cs
       
     2 
       
     3 using System;
       
     4 using System.IO;
       
     5 
       
     6 namespace SevenZip
       
     7 {
       
     8 	/// <summary>
       
     9 	/// LZMA Benchmark
       
    10 	/// </summary>
       
    11 	internal abstract class LzmaBench
       
    12 	{
       
    13 		const UInt32 kAdditionalSize = (6 << 20);
       
    14 		const UInt32 kCompressedAdditionalSize = (1 << 10);
       
    15 		const UInt32 kMaxLzmaPropSize = 10;
       
    16 
       
    17 		class CRandomGenerator
       
    18 		{
       
    19 			UInt32 A1;
       
    20 			UInt32 A2;
       
    21 			public CRandomGenerator() { Init(); }
       
    22 			public void Init() { A1 = 362436069; A2 = 521288629; }
       
    23 			public UInt32 GetRnd()
       
    24 			{
       
    25 				return
       
    26 					((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^
       
    27 					((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)));
       
    28 			}
       
    29 		};
       
    30 
       
    31 		class CBitRandomGenerator
       
    32 		{
       
    33 			CRandomGenerator RG = new CRandomGenerator();
       
    34 			UInt32 Value;
       
    35 			int NumBits;
       
    36 			public void Init()
       
    37 			{
       
    38 				Value = 0;
       
    39 				NumBits = 0;
       
    40 			}
       
    41 			public UInt32 GetRnd(int numBits)
       
    42 			{
       
    43 				UInt32 result;
       
    44 				if (NumBits > numBits)
       
    45 				{
       
    46 					result = Value & (((UInt32)1 << numBits) - 1);
       
    47 					Value >>= numBits;
       
    48 					NumBits -= numBits;
       
    49 					return result;
       
    50 				}
       
    51 				numBits -= NumBits;
       
    52 				result = (Value << numBits);
       
    53 				Value = RG.GetRnd();
       
    54 				result |= Value & (((UInt32)1 << numBits) - 1);
       
    55 				Value >>= numBits;
       
    56 				NumBits = 32 - numBits;
       
    57 				return result;
       
    58 			}
       
    59 		};
       
    60 
       
    61 		class CBenchRandomGenerator
       
    62 		{
       
    63 			CBitRandomGenerator RG = new CBitRandomGenerator();
       
    64 			UInt32 Pos;
       
    65 			UInt32 Rep0;
       
    66 			
       
    67 			public UInt32 BufferSize;
       
    68 			public Byte[] Buffer = null;
       
    69 
       
    70 			public CBenchRandomGenerator() { }
       
    71 
       
    72 			public void Set(UInt32 bufferSize)
       
    73 			{
       
    74 				Buffer = new Byte[bufferSize];
       
    75 				Pos = 0;
       
    76 				BufferSize = bufferSize;
       
    77 			}
       
    78 			UInt32 GetRndBit() { return RG.GetRnd(1); }
       
    79 			UInt32 GetLogRandBits(int numBits)
       
    80 			{
       
    81 				UInt32 len = RG.GetRnd(numBits);
       
    82 				return RG.GetRnd((int)len);
       
    83 			}
       
    84 			UInt32 GetOffset()
       
    85 			{
       
    86 				if (GetRndBit() == 0)
       
    87 					return GetLogRandBits(4);
       
    88 				return (GetLogRandBits(4) << 10) | RG.GetRnd(10);
       
    89 			}
       
    90 			UInt32 GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); }
       
    91 			UInt32 GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); }
       
    92 			public void Generate()
       
    93 			{
       
    94 				RG.Init();
       
    95 				Rep0 = 1;
       
    96 				while (Pos < BufferSize)
       
    97 				{
       
    98 					if (GetRndBit() == 0 || Pos < 1)
       
    99 						Buffer[Pos++] = (Byte)RG.GetRnd(8);
       
   100 					else
       
   101 					{
       
   102 						UInt32 len;
       
   103 						if (RG.GetRnd(3) == 0)
       
   104 							len = 1 + GetLen1();
       
   105 						else
       
   106 						{
       
   107 							do
       
   108 								Rep0 = GetOffset();
       
   109 							while (Rep0 >= Pos);
       
   110 							Rep0++;
       
   111 							len = 2 + GetLen2();
       
   112 						}
       
   113 						for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++)
       
   114 							Buffer[Pos] = Buffer[Pos - Rep0];
       
   115 					}
       
   116 				}
       
   117 			}
       
   118 		};
       
   119 
       
   120 		class CrcOutStream : System.IO.Stream
       
   121 		{
       
   122 			public CRC CRC = new CRC();
       
   123 			public void Init() { CRC.Init(); }
       
   124 			public UInt32 GetDigest() { return CRC.GetDigest(); }
       
   125 
       
   126 			public override bool CanRead { get { return false; } }
       
   127 			public override bool CanSeek { get { return false; } }
       
   128 			public override bool CanWrite { get { return true; } }
       
   129 			public override Int64 Length { get { return 0; } }
       
   130 			public override Int64 Position { get { return 0; } set { } }
       
   131 			public override void Flush() { }
       
   132 			public override long Seek(long offset, SeekOrigin origin) { return 0; }
       
   133 			public override void SetLength(long value) { }
       
   134 			public override int Read(byte[] buffer, int offset, int count) { return 0; }
       
   135 
       
   136 			public override void WriteByte(byte b)
       
   137 			{
       
   138 				CRC.UpdateByte(b);
       
   139 			}
       
   140 			public override void Write(byte[] buffer, int offset, int count)
       
   141 			{
       
   142 				CRC.Update(buffer, (uint)offset, (uint)count);
       
   143 			}
       
   144 		};
       
   145 
       
   146 		class CProgressInfo : ICodeProgress
       
   147 		{
       
   148 			public Int64 ApprovedStart;
       
   149 			public Int64 InSize;
       
   150 			public System.DateTime Time;
       
   151 			public void Init() { InSize = 0; }
       
   152 			public void SetProgress(Int64 inSize, Int64 outSize)
       
   153 			{
       
   154 				if (inSize >= ApprovedStart && InSize == 0)
       
   155 				{
       
   156 					Time = DateTime.UtcNow;
       
   157 					InSize = inSize;
       
   158 				}
       
   159 			}
       
   160 		}
       
   161 		const int kSubBits = 8;
       
   162 
       
   163 		static UInt32 GetLogSize(UInt32 size)
       
   164 		{
       
   165 			for (int i = kSubBits; i < 32; i++)
       
   166 				for (UInt32 j = 0; j < (1 << kSubBits); j++)
       
   167 					if (size <= (((UInt32)1) << i) + (j << (i - kSubBits)))
       
   168 						return (UInt32)(i << kSubBits) + j;
       
   169 			return (32 << kSubBits);
       
   170 		}
       
   171 
       
   172 		static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime)
       
   173 		{
       
   174 			UInt64 freq = TimeSpan.TicksPerSecond;
       
   175 			UInt64 elTime = elapsedTime;
       
   176 			while (freq > 1000000)
       
   177 			{
       
   178 				freq >>= 1;
       
   179 				elTime >>= 1;
       
   180 			}
       
   181 			if (elTime == 0)
       
   182 				elTime = 1;
       
   183 			return value * freq / elTime;
       
   184 		}
       
   185 
       
   186 		static UInt64 GetCompressRating(UInt32 dictionarySize, UInt64 elapsedTime, UInt64 size)
       
   187 		{
       
   188 			UInt64 t = GetLogSize(dictionarySize) - (18 << kSubBits);
       
   189 			UInt64 numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits));
       
   190 			UInt64 numCommands = (UInt64)(size) * numCommandsForOne;
       
   191 			return MyMultDiv64(numCommands, elapsedTime);
       
   192 		}
       
   193 
       
   194 		static UInt64 GetDecompressRating(UInt64 elapsedTime, UInt64 outSize, UInt64 inSize)
       
   195 		{
       
   196 			UInt64 numCommands = inSize * 220 + outSize * 20;
       
   197 			return MyMultDiv64(numCommands, elapsedTime);
       
   198 		}
       
   199 
       
   200 		static UInt64 GetTotalRating(
       
   201 			UInt32 dictionarySize,
       
   202 			UInt64 elapsedTimeEn, UInt64 sizeEn,
       
   203 			UInt64 elapsedTimeDe,
       
   204 			UInt64 inSizeDe, UInt64 outSizeDe)
       
   205 		{
       
   206 			return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) +
       
   207 				GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2;
       
   208 		}
       
   209 
       
   210 		static void PrintValue(UInt64 v)
       
   211 		{
       
   212 			string s = v.ToString();
       
   213 			for (int i = 0; i + s.Length < 6; i++)
       
   214 				System.Console.Write(" ");
       
   215 			System.Console.Write(s);
       
   216 		}
       
   217 
       
   218 		static void PrintRating(UInt64 rating)
       
   219 		{
       
   220 			PrintValue(rating / 1000000);
       
   221 			System.Console.Write(" MIPS");
       
   222 		}
       
   223 
       
   224 		static void PrintResults(
       
   225 			UInt32 dictionarySize,
       
   226 			UInt64 elapsedTime,
       
   227 			UInt64 size,
       
   228 			bool decompressMode, UInt64 secondSize)
       
   229 		{
       
   230 			UInt64 speed = MyMultDiv64(size, elapsedTime);
       
   231 			PrintValue(speed / 1024);
       
   232 			System.Console.Write(" KB/s  ");
       
   233 			UInt64 rating;
       
   234 			if (decompressMode)
       
   235 				rating = GetDecompressRating(elapsedTime, size, secondSize);
       
   236 			else
       
   237 				rating = GetCompressRating(dictionarySize, elapsedTime, size);
       
   238 			PrintRating(rating);
       
   239 		}
       
   240 
       
   241 		static public int LzmaBenchmark(Int32 numIterations, UInt32 dictionarySize)
       
   242 		{
       
   243 			if (numIterations <= 0)
       
   244 				return 0;
       
   245 			if (dictionarySize < (1 << 18))
       
   246 			{
       
   247 				System.Console.WriteLine("\nError: dictionary size for benchmark must be >= 19 (512 KB)");
       
   248 				return 1;
       
   249 			}
       
   250 			System.Console.Write("\n       Compressing                Decompressing\n\n");
       
   251 
       
   252 			Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder();
       
   253 			Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder();
       
   254 
       
   255 
       
   256 			CoderPropID[] propIDs = 
       
   257 			{ 
       
   258 				CoderPropID.DictionarySize,
       
   259 			};
       
   260 			object[] properties = 
       
   261 			{
       
   262 				(Int32)(dictionarySize),
       
   263 			};
       
   264 
       
   265 			UInt32 kBufferSize = dictionarySize + kAdditionalSize;
       
   266 			UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize;
       
   267 
       
   268 			encoder.SetCoderProperties(propIDs, properties);
       
   269 			System.IO.MemoryStream propStream = new System.IO.MemoryStream();
       
   270 			encoder.WriteCoderProperties(propStream);
       
   271 			byte[] propArray = propStream.ToArray();
       
   272 
       
   273 			CBenchRandomGenerator rg = new CBenchRandomGenerator();
       
   274 
       
   275 			rg.Set(kBufferSize);
       
   276 			rg.Generate();
       
   277 			CRC crc = new CRC();
       
   278 			crc.Init();
       
   279 			crc.Update(rg.Buffer, 0, rg.BufferSize);
       
   280 
       
   281 			CProgressInfo progressInfo = new CProgressInfo();
       
   282 			progressInfo.ApprovedStart = dictionarySize;
       
   283 
       
   284 			UInt64 totalBenchSize = 0;
       
   285 			UInt64 totalEncodeTime = 0;
       
   286 			UInt64 totalDecodeTime = 0;
       
   287 			UInt64 totalCompressedSize = 0;
       
   288 
       
   289 			MemoryStream inStream = new MemoryStream(rg.Buffer, 0, (int)rg.BufferSize);
       
   290 			MemoryStream compressedStream = new MemoryStream((int)kCompressedBufferSize);
       
   291 			CrcOutStream crcOutStream = new CrcOutStream();
       
   292 			for (Int32 i = 0; i < numIterations; i++)
       
   293 			{
       
   294 				progressInfo.Init();
       
   295 				inStream.Seek(0, SeekOrigin.Begin);
       
   296 				compressedStream.Seek(0, SeekOrigin.Begin);
       
   297 				encoder.Code(inStream, compressedStream, -1, -1, progressInfo);
       
   298 				TimeSpan sp2 = DateTime.UtcNow - progressInfo.Time;
       
   299 				UInt64 encodeTime = (UInt64)sp2.Ticks;
       
   300 
       
   301 				long compressedSize = compressedStream.Position;
       
   302 				if (progressInfo.InSize == 0)
       
   303 					throw (new Exception("Internal ERROR 1282"));
       
   304 
       
   305 				UInt64 decodeTime = 0;
       
   306 				for (int j = 0; j < 2; j++)
       
   307 				{
       
   308 					compressedStream.Seek(0, SeekOrigin.Begin);
       
   309 					crcOutStream.Init();
       
   310 
       
   311 					decoder.SetDecoderProperties(propArray);
       
   312 					UInt64 outSize = kBufferSize;
       
   313 					System.DateTime startTime = DateTime.UtcNow;
       
   314 					decoder.Code(compressedStream, crcOutStream, 0, (Int64)outSize, null);
       
   315 					TimeSpan sp = (DateTime.UtcNow - startTime);
       
   316 					decodeTime = (ulong)sp.Ticks;
       
   317 					if (crcOutStream.GetDigest() != crc.GetDigest())
       
   318 						throw (new Exception("CRC Error"));
       
   319 				}
       
   320 				UInt64 benchSize = kBufferSize - (UInt64)progressInfo.InSize;
       
   321 				PrintResults(dictionarySize, encodeTime, benchSize, false, 0);
       
   322 				System.Console.Write("     ");
       
   323 				PrintResults(dictionarySize, decodeTime, kBufferSize, true, (ulong)compressedSize);
       
   324 				System.Console.WriteLine();
       
   325 
       
   326 				totalBenchSize += benchSize;
       
   327 				totalEncodeTime += encodeTime;
       
   328 				totalDecodeTime += decodeTime;
       
   329 				totalCompressedSize += (ulong)compressedSize;
       
   330 			}
       
   331 			System.Console.WriteLine("---------------------------------------------------");
       
   332 			PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0);
       
   333 			System.Console.Write("     ");
       
   334 			PrintResults(dictionarySize, totalDecodeTime,
       
   335 					kBufferSize * (UInt64)numIterations, true, totalCompressedSize);
       
   336 			System.Console.WriteLine("    Average");
       
   337 			return 0;
       
   338 		}
       
   339 	}
       
   340 }