tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

LzmaBench.cs (9778B)


      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 }