📄 lzmabench.cs
字号:
// LzmaBench.cs
using System;
using System.IO;
namespace SevenZip
{
/// <summary>
/// LZMA Benchmark
/// </summary>
internal abstract class LzmaBench
{
const UInt32 kAdditionalSize = (6 << 20);
const UInt32 kCompressedAdditionalSize = (1 << 10);
const UInt32 kMaxLzmaPropSize = 10;
class CRandomGenerator
{
UInt32 A1;
UInt32 A2;
public CRandomGenerator() { Init(); }
public void Init() { A1 = 362436069; A2 = 521288629; }
public UInt32 GetRnd()
{
return
((A1 = 36969 * (A1 & 0xffff) + (A1 >> 16)) << 16) ^
((A2 = 18000 * (A2 & 0xffff) + (A2 >> 16)));
}
};
class CBitRandomGenerator
{
CRandomGenerator RG = new CRandomGenerator();
UInt32 Value;
int NumBits;
public void Init()
{
Value = 0;
NumBits = 0;
}
public UInt32 GetRnd(int numBits)
{
UInt32 result;
if (NumBits > numBits)
{
result = Value & (((UInt32)1 << numBits) - 1);
Value >>= numBits;
NumBits -= numBits;
return result;
}
numBits -= NumBits;
result = (Value << numBits);
Value = RG.GetRnd();
result |= Value & (((UInt32)1 << numBits) - 1);
Value >>= numBits;
NumBits = 32 - numBits;
return result;
}
};
class CBenchRandomGenerator
{
CBitRandomGenerator RG = new CBitRandomGenerator();
UInt32 Pos;
public UInt32 BufferSize;
public Byte[] Buffer = null;
public CBenchRandomGenerator() { }
public void Init() { RG.Init(); }
public void Set(UInt32 bufferSize)
{
Buffer = new Byte[bufferSize];
Pos = 0;
BufferSize = bufferSize;
}
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((int)len);
}
UInt32 GetOffset()
{
if (GetRndBit() == 0)
return GetLogRandBits(4);
return (GetLogRandBits(4) << 10) | RG.GetRnd(10);
}
UInt32 GetLen()
{
if (GetRndBit() == 0)
return RG.GetRnd(2);
if (GetRndBit() == 0)
return 4 + RG.GetRnd(3);
return 12 + RG.GetRnd(4);
}
public void Generate()
{
while (Pos < BufferSize)
{
if (GetRndBit() == 0 || Pos < 1)
Buffer[Pos++] = (Byte)(RG.GetRnd(8));
else
{
UInt32 offset = GetOffset();
while (offset >= Pos)
offset >>= 1;
offset += 1;
UInt32 len = 2 + GetLen();
for (UInt32 i = 0; i < len && Pos < BufferSize; i++, Pos++)
Buffer[Pos] = Buffer[Pos - offset];
}
}
}
};
class CrcOutStream : System.IO.Stream
{
public CRC CRC = new CRC();
public void Init() { CRC.Init(); }
public UInt32 GetDigest() { return CRC.GetDigest(); }
public override bool CanRead { get { return false; } }
public override bool CanSeek { get { return false; } }
public override bool CanWrite { get { return true; } }
public override Int64 Length { get { return 0; } }
public override Int64 Position { get { return 0; } set { } }
public override void Flush() { }
public override long Seek(long offset, SeekOrigin origin) { return 0; }
public override void SetLength(long value) { }
public override int Read(byte[] buffer, int offset, int count) { return 0; }
public override void WriteByte(byte b)
{
CRC.UpdateByte(b);
}
public override void Write(byte[] buffer, int offset, int count)
{
CRC.Update(buffer, (uint)offset, (uint)count);
}
};
class CProgressInfo : ICodeProgress
{
public Int64 ApprovedStart;
public Int64 InSize;
public System.DateTime Time;
public void Init() { InSize = 0; }
public void SetProgress(Int64 inSize, Int64 outSize)
{
if (inSize >= ApprovedStart && InSize == 0)
{
Time = DateTime.UtcNow;
InSize = inSize;
}
}
}
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 (UInt32)(i << kSubBits) + j;
return (32 << kSubBits);
}
static UInt64 MyMultDiv64(UInt64 value, UInt64 elapsedTime)
{
UInt64 freq = TimeSpan.TicksPerSecond;
UInt64 elTime = elapsedTime;
while (freq > 1000000)
{
freq >>= 1;
elTime >>= 1;
}
if (elTime == 0)
elTime = 1;
return value * freq / elTime;
}
static UInt64 GetCompressRating(UInt32 dictionarySize, bool isBT4,
UInt64 elapsedTime, UInt64 size)
{
UInt64 numCommandsForOne;
if (isBT4)
{
UInt64 t = GetLogSize(dictionarySize) - (19 << kSubBits);
numCommandsForOne = 2000 + ((t * t * 68) >> (2 * kSubBits));
}
else
{
UInt64 t = GetLogSize(dictionarySize) - (15 << kSubBits);
numCommandsForOne = 1500 + ((t * t * 41) >> (2 * kSubBits));
}
UInt64 numCommands = (UInt64)(size) * numCommandsForOne;
return MyMultDiv64(numCommands, elapsedTime);
}
static UInt64 GetDecompressRating(UInt64 elapsedTime,
UInt64 outSize, UInt64 inSize)
{
UInt64 numCommands = inSize * 250 + outSize * 21;
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 PrintValue(UInt64 v)
{
string s = v.ToString();
for (int i = 0; i + s.Length < 6; i++)
System.Console.Write(" ");
System.Console.Write(s);
}
static void PrintRating(UInt64 rating)
{
PrintValue(rating / 1000000);
System.Console.Write(" MIPS");
}
static void PrintResults(
UInt32 dictionarySize,
bool isBT4,
UInt64 elapsedTime,
UInt64 size,
bool decompressMode, UInt64 secondSize)
{
UInt64 speed = MyMultDiv64(size, elapsedTime);
PrintValue(speed / 1024);
System.Console.Write(" KB/s ");
UInt64 rating;
if (decompressMode)
rating = GetDecompressRating(elapsedTime, size, secondSize);
else
rating = GetCompressRating(dictionarySize, isBT4, elapsedTime, size);
PrintRating(rating);
}
const string bt2 = "BT2";
const string bt4 = "BT4";
static public int LzmaBenchmark(Int32 numIterations, UInt32 dictionarySize, bool isBT4)
{
if (numIterations <= 0)
return 0;
if (dictionarySize < (1 << 19) && isBT4 || dictionarySize < (1 << 15))
{
System.Console.WriteLine("\nError: dictionary size for benchmark must be >= 19 (512 KB)");
return 1;
}
System.Console.Write("\n Compressing Decompressing\n\n");
Compression.LZMA.Encoder encoder = new Compression.LZMA.Encoder();
Compression.LZMA.Decoder decoder = new Compression.LZMA.Decoder();
CoderPropID[] propIDs =
{
CoderPropID.DictionarySize,
CoderPropID.MatchFinder
};
object[] properties =
{
(Int32)(dictionarySize),
isBT4 ? bt4: bt2
};
UInt32 kBufferSize = dictionarySize + kAdditionalSize;
UInt32 kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize;
encoder.SetCoderProperties(propIDs, properties);
System.IO.MemoryStream propStream = new System.IO.MemoryStream();
encoder.WriteCoderProperties(propStream);
byte[] propArray = propStream.ToArray();
CBenchRandomGenerator rg = new CBenchRandomGenerator();
rg.Init();
rg.Set(kBufferSize);
rg.Generate();
CRC crc = new CRC();
crc.Init();
crc.Update(rg.Buffer, 0, rg.BufferSize);
CProgressInfo progressInfo = new CProgressInfo();
progressInfo.ApprovedStart = dictionarySize;
UInt64 totalBenchSize = 0;
UInt64 totalEncodeTime = 0;
UInt64 totalDecodeTime = 0;
UInt64 totalCompressedSize = 0;
MemoryStream inStream = new MemoryStream(rg.Buffer, 0, (int)rg.BufferSize);
MemoryStream compressedStream = new MemoryStream((int)kCompressedBufferSize);
CrcOutStream crcOutStream = new CrcOutStream();
for (Int32 i = 0; i < numIterations; i++)
{
progressInfo.Init();
inStream.Seek(0, SeekOrigin.Begin);
compressedStream.Seek(0, SeekOrigin.Begin);
encoder.Code(inStream, compressedStream, -1, -1, progressInfo);
TimeSpan sp2 = DateTime.UtcNow - progressInfo.Time;
UInt64 encodeTime = (UInt64)sp2.Ticks;
long compressedSize = compressedStream.Position;
if (progressInfo.InSize == 0)
throw (new Exception("Internal ERROR 1282"));
UInt64 decodeTime = 0;
for (int j = 0; j < 2; j++)
{
compressedStream.Seek(0, SeekOrigin.Begin);
crcOutStream.Init();
decoder.SetDecoderProperties(propArray);
UInt64 outSize = kBufferSize;
System.DateTime startTime = DateTime.UtcNow;
decoder.Code(compressedStream, crcOutStream, 0, (Int64)outSize, null);
TimeSpan sp = (DateTime.UtcNow - startTime);
decodeTime = (ulong)sp.Ticks;
if (crcOutStream.GetDigest() != crc.GetDigest())
throw (new Exception("CRC Error"));
}
UInt64 benchSize = kBufferSize - (UInt64)progressInfo.InSize;
PrintResults(dictionarySize, isBT4, encodeTime, benchSize, false, 0);
System.Console.Write(" ");
PrintResults(dictionarySize, isBT4, decodeTime, kBufferSize, true, (ulong)compressedSize);
System.Console.WriteLine();
totalBenchSize += benchSize;
totalEncodeTime += encodeTime;
totalDecodeTime += decodeTime;
totalCompressedSize += (ulong)compressedSize;
}
System.Console.WriteLine("---------------------------------------------------");
PrintResults(dictionarySize, isBT4, totalEncodeTime, totalBenchSize, false, 0);
System.Console.Write(" ");
PrintResults(dictionarySize, isBT4, totalDecodeTime,
kBufferSize * (UInt64)numIterations, true, totalCompressedSize);
System.Console.WriteLine(" Average");
return 0;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -