package SevenZip;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public class LzmaBench
{
static final int kAdditionalSize = 1 << 21;
static final int kCompressedAdditionalSize = 1 << 10;
static class CRandomGenerator
{
int A1;
int A2;
public CRandomGenerator()
{
Init();
}
public void Init()
{
A1 = 362436069;
A2 = 521288629;
}
public int GetRnd()
{
return (A1 = 36969 * (A1 & 0xffff) + (A1 >>> 16)) << 16
^ (A2 = 18000 * (A2 & 0xffff) + (A2 >>> 16));
}
};
static class CBitRandomGenerator
{
CRandomGenerator RG = new CRandomGenerator();
int Value;
int NumBits;
public void Init()
{
Value = 0;
NumBits = 0;
}
public int GetRnd(int numBits)
{
int result;
if (NumBits > numBits)
{
result = Value & (1 << numBits) - 1;
Value >>>= numBits;
NumBits -= numBits;
return result;
}
numBits -= NumBits;
result = Value << numBits;
Value = RG.GetRnd();
result |= Value & (1 << numBits) - 1;
Value >>>= numBits;
NumBits = 32 - numBits;
return result;
}
};
static class CBenchRandomGenerator
{
CBitRandomGenerator RG = new CBitRandomGenerator();
int Pos;
int Rep0;
public int BufferSize;
public byte[] Buffer = null;
public CBenchRandomGenerator()
{
}
public void Set(int bufferSize)
{
Buffer = new byte[bufferSize];
Pos = 0;
BufferSize = bufferSize;
}
int GetRndBit()
{
return RG.GetRnd(1);
}
int GetLogRandBits(int numBits)
{
final int len = RG.GetRnd(numBits);
return RG.GetRnd(len);
}
int GetOffset()
{
if (GetRndBit() == 0)
{
return GetLogRandBits(4);
}
return GetLogRandBits(4) << 10 | RG.GetRnd(10);
}
int GetLen1()
{
return RG.GetRnd(1 + RG.GetRnd(2));
}
int GetLen2()
{
return RG.GetRnd(2 + RG.GetRnd(2));
}
public void Generate()
{
RG.Init();
Rep0 = 1;
while (Pos < BufferSize)
{
if (GetRndBit() == 0 || Pos < 1)
{
Buffer[Pos++] = (byte) RG.GetRnd(8);
}
else
{
int len;
if (RG.GetRnd(3) == 0)
{
len = 1 + GetLen1();
}
else
{
do
{
Rep0 = GetOffset();
} while (Rep0 >= Pos);
Rep0++;
len = 2 + GetLen2();
}
for (int i = 0; i < len && Pos < BufferSize; i++, Pos++)
{
Buffer[Pos] = Buffer[Pos - Rep0];
}
}
}
}
};
static class CrcOutStream extends java.io.OutputStream
{
public CRC CRC = new CRC();
public void Init()
{
CRC.Init();
}
public int GetDigest()
{
return CRC.GetDigest();
}
public void write(byte[] b)
{
CRC.Update(b);
}
public void write(byte[] b, int off, int len)
{
CRC.Update(b, off, len);
}
public void write(int b)
{
CRC.UpdateByte(b);
}
};
static class MyOutputStream extends java.io.OutputStream
{
byte[] _buffer;
int _size;
int _pos;
public MyOutputStream(byte[] buffer)
{
_buffer = buffer;
_size = _buffer.length;
}
public void reset()
{
_pos = 0;
}
public void write(int b) throws IOException
{
if (_pos >= _size)
{
throw new IOException("Error");
}
_buffer[_pos++] = (byte) b;
}
public int size()
{
return _pos;
}
};
static class MyInputStream extends java.io.InputStream
{
byte[] _buffer;
int _size;
int _pos;
public MyInputStream(byte[] buffer, int size)
{
_buffer = buffer;
_size = size;
}
public void reset()
{
_pos = 0;
}
public int read()
{
if (_pos >= _size)
{
return -1;
}
return _buffer[_pos++] & 0xFF;
}
};
static class CProgressInfo implements ICodeProgress
{
public long ApprovedStart;
public long InSize;
public long Time;
public void Init()
{
InSize = 0;
}
public void SetProgress(long inSize, long outSize)
{
if (inSize >= ApprovedStart && InSize == 0)
{
Time = System.currentTimeMillis();
InSize = inSize;
}
}
}
static final int kSubBits = 8;
static int GetLogSize(int size)
{
for (int i = kSubBits; i < 32; i++)
{
for (int j = 0; j < 1 << kSubBits; j++)
{
if (size <= (1 << i) + (j << i - kSubBits))
{
return (i << kSubBits) + j;
}
}
}
return 32 << kSubBits;
}
static long MyMultDiv64(long value, long elapsedTime)
{
long freq = 1000; // ms
long elTime = elapsedTime;
while (freq > 1000000)
{
freq >>>= 1;
elTime >>>= 1;
}
if (elTime == 0)
{
elTime = 1;
}
return value * freq / elTime;
}
static long GetCompressRating(int dictionarySize, long elapsedTime,
long size)
{
final long t = GetLogSize(dictionarySize) - (18 << kSubBits);
final long numCommandsForOne = 1060 + (t * t * 10 >> 2 * kSubBits);
final long numCommands = size * numCommandsForOne;
return MyMultDiv64(numCommands, elapsedTime);
}
static long GetDecompressRating(long elapsedTime, long outSize, long inSize)
{
final long numCommands = inSize * 220 + outSize * 20;
return MyMultDiv64(numCommands, elapsedTime);
}
static long GetTotalRating(int dictionarySize, long elapsedTimeEn,
long sizeEn, long elapsedTimeDe, long inSizeDe, long outSizeDe)
{
return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) + GetDecompressRating(
elapsedTimeDe, inSizeDe, outSizeDe)) / 2;
}
static void PrintValue(long v)
{
String s = "";
s += v;
for (int i = 0; i + s.length() < 6; i++)
{
System.out.print(" ");
}
System.out.print(s);
}
static void PrintRating(long rating)
{
PrintValue(rating / 1000000);
System.out.print(" MIPS");
}
static void PrintResults(int dictionarySize, long elapsedTime, long size,
boolean decompressMode, long secondSize)
{
final long speed = MyMultDiv64(size, elapsedTime);
PrintValue(speed / 1024);
System.out.print(" KB/s ");
long rating;
if (decompressMode)
{
rating = GetDecompressRating(elapsedTime, size, secondSize);
}
else
{
rating = GetCompressRating(dictionarySize, elapsedTime, size);
}
PrintRating(rating);
}
static public int LzmaBenchmark(int numIterations, int dictionarySize)
throws Exception
{
if (numIterations <= 0)
{
return 0;
}
if (dictionarySize < 1 << 18)
{
System.out
.println("\nError: dictionary size for benchmark must be >= 18 (256 KB)");
return 1;
}
System.out
.print("\n Compressing Decompressing\n\n");
final SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder();
final SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder();
if (!encoder.SetDictionarySize(dictionarySize))
{
throw new Exception("Incorrect dictionary size");
}
final int kBufferSize = dictionarySize + kAdditionalSize;
final int kCompressedBufferSize = kBufferSize / 2
+ kCompressedAdditionalSize;
final ByteArrayOutputStream propStream = new ByteArrayOutputStream();
encoder.WriteCoderProperties(propStream);
final byte[] propArray = propStream.toByteArray();
decoder.SetDecoderProperties(propArray);
final CBenchRandomGenerator rg = new CBenchRandomGenerator();
rg.Set(kBufferSize);
rg.Generate();
final CRC crc = new CRC();
crc.Init();
crc.Update(rg.Buffer, 0, rg.BufferSize);
final CProgressInfo progressInfo = new CProgressInfo();
progressInfo.ApprovedStart = dictionarySize;
long totalBenchSize = 0;
long totalEncodeTime = 0;
long totalDecodeTime = 0;
long totalCompressedSize = 0;
final MyInputStream inStream = new MyInputStream(rg.Buffer,
rg.BufferSize);
final byte[] compressedBuffer = new byte[kCompressedBufferSize];
final MyOutputStream compressedStream = new MyOutputStream(
compressedBuffer);
final CrcOutStream crcOutStream = new CrcOutStream();
MyInputStream inputCompressedStream = null;
int compressedSize = 0;
for (int i = 0; i < numIterations; i++)
{
progressInfo.Init();
inStream.reset();
compressedStream.reset();
encoder.Code(inStream, compressedStream, -1, -1, progressInfo);
final long encodeTime = System.currentTimeMillis()
- progressInfo.Time;
if (i == 0)
{
compressedSize = compressedStream.size();
inputCompressedStream = new MyInputStream(compressedBuffer,
compressedSize);
}
else if (compressedSize != compressedStream.size())
{
throw new Exception("Encoding error");
}
if (progressInfo.InSize == 0)
{
throw new Exception("Internal ERROR 1282");
}
long decodeTime = 0;
for (int j = 0; j < 2; j++)
{
inputCompressedStream.reset();
crcOutStream.Init();
final long outSize = kBufferSize;
final long startTime = System.currentTimeMillis();
if (!decoder.Code(inputCompressedStream, crcOutStream, outSize))
{
throw new Exception("Decoding Error");
}
;
decodeTime = System.currentTimeMillis() - startTime;
if (crcOutStream.GetDigest() != crc.GetDigest())
{
throw new Exception("CRC Error");
}
}
final long benchSize = kBufferSize - progressInfo.InSize;
PrintResults(dictionarySize, encodeTime, benchSize, false, 0);
System.out.print(" ");
PrintResults(dictionarySize, decodeTime, kBufferSize, true,
compressedSize);
System.out.println();
totalBenchSize += benchSize;
totalEncodeTime += encodeTime;
totalDecodeTime += decodeTime;
totalCompressedSize += compressedSize;
}
System.out
.println("---------------------------------------------------");
PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0);
System.out.print(" ");
PrintResults(dictionarySize, totalDecodeTime, kBufferSize
* (long) numIterations, true, totalCompressedSize);
System.out.println(" Average");
return 0;
}
}