001: package SevenZip;
002:
003: import java.io.ByteArrayOutputStream;
004: import java.io.IOException;
005:
006: public class LzmaBench {
007: static final int kAdditionalSize = (1 << 21);
008: static final int kCompressedAdditionalSize = (1 << 10);
009:
010: static class CRandomGenerator {
011: int A1;
012: int A2;
013:
014: public CRandomGenerator() {
015: Init();
016: }
017:
018: public void Init() {
019: A1 = 362436069;
020: A2 = 521288629;
021: }
022:
023: public int GetRnd() {
024: return ((A1 = 36969 * (A1 & 0xffff) + (A1 >>> 16)) << 16)
025: ^ ((A2 = 18000 * (A2 & 0xffff) + (A2 >>> 16)));
026: }
027: };
028:
029: static class CBitRandomGenerator {
030: CRandomGenerator RG = new CRandomGenerator();
031: int Value;
032: int NumBits;
033:
034: public void Init() {
035: Value = 0;
036: NumBits = 0;
037: }
038:
039: public int GetRnd(int numBits) {
040: int result;
041: if (NumBits > numBits) {
042: result = Value & ((1 << numBits) - 1);
043: Value >>>= numBits;
044: NumBits -= numBits;
045: return result;
046: }
047: numBits -= NumBits;
048: result = (Value << numBits);
049: Value = RG.GetRnd();
050: result |= Value & ((1 << numBits) - 1);
051: Value >>>= numBits;
052: NumBits = 32 - numBits;
053: return result;
054: }
055: };
056:
057: static class CBenchRandomGenerator {
058: CBitRandomGenerator RG = new CBitRandomGenerator();
059: int Pos;
060: int Rep0;
061:
062: public int BufferSize;
063: public byte[] Buffer = null;
064:
065: public CBenchRandomGenerator() {
066: }
067:
068: public void Set(int bufferSize) {
069: Buffer = new byte[bufferSize];
070: Pos = 0;
071: BufferSize = bufferSize;
072: }
073:
074: int GetRndBit() {
075: return RG.GetRnd(1);
076: }
077:
078: int GetLogRandBits(int numBits) {
079: int len = RG.GetRnd(numBits);
080: return RG.GetRnd(len);
081: }
082:
083: int GetOffset() {
084: if (GetRndBit() == 0)
085: return GetLogRandBits(4);
086: return (GetLogRandBits(4) << 10) | RG.GetRnd(10);
087: }
088:
089: int GetLen1() {
090: return RG.GetRnd(1 + RG.GetRnd(2));
091: }
092:
093: int GetLen2() {
094: return RG.GetRnd(2 + RG.GetRnd(2));
095: }
096:
097: public void Generate() {
098: RG.Init();
099: Rep0 = 1;
100: while (Pos < BufferSize) {
101: if (GetRndBit() == 0 || Pos < 1)
102: Buffer[Pos++] = (byte) (RG.GetRnd(8));
103: else {
104: int len;
105: if (RG.GetRnd(3) == 0)
106: len = 1 + GetLen1();
107: else {
108: do
109: Rep0 = GetOffset();
110: while (Rep0 >= Pos);
111: Rep0++;
112: len = 2 + GetLen2();
113: }
114: for (int i = 0; i < len && Pos < BufferSize; i++, Pos++)
115: Buffer[Pos] = Buffer[Pos - Rep0];
116: }
117: }
118: }
119: };
120:
121: static class CrcOutStream extends java.io.OutputStream {
122: public CRC CRC = new CRC();
123:
124: public void Init() {
125: CRC.Init();
126: }
127:
128: public int GetDigest() {
129: return CRC.GetDigest();
130: }
131:
132: public void write(byte[] b) {
133: CRC.Update(b);
134: }
135:
136: public void write(byte[] b, int off, int len) {
137: CRC.Update(b, off, len);
138: }
139:
140: public void write(int b) {
141: CRC.UpdateByte(b);
142: }
143: };
144:
145: static class MyOutputStream extends java.io.OutputStream {
146: byte[] _buffer;
147: int _size;
148: int _pos;
149:
150: public MyOutputStream(byte[] buffer) {
151: _buffer = buffer;
152: _size = _buffer.length;
153: }
154:
155: public void reset() {
156: _pos = 0;
157: }
158:
159: public void write(int b) throws IOException {
160: if (_pos >= _size)
161: throw new IOException("Error");
162: _buffer[_pos++] = (byte) b;
163: }
164:
165: public int size() {
166: return _pos;
167: }
168: };
169:
170: static class MyInputStream extends java.io.InputStream {
171: byte[] _buffer;
172: int _size;
173: int _pos;
174:
175: public MyInputStream(byte[] buffer, int size) {
176: _buffer = buffer;
177: _size = size;
178: }
179:
180: public void reset() {
181: _pos = 0;
182: }
183:
184: public int read() {
185: if (_pos >= _size)
186: return -1;
187: return _buffer[_pos++] & 0xFF;
188: }
189: };
190:
191: static class CProgressInfo implements ICodeProgress {
192: public long ApprovedStart;
193: public long InSize;
194: public long Time;
195:
196: public void Init() {
197: InSize = 0;
198: }
199:
200: public void SetProgress(long inSize, long outSize) {
201: if (inSize >= ApprovedStart && InSize == 0) {
202: Time = System.currentTimeMillis();
203: InSize = inSize;
204: }
205: }
206: }
207:
208: static final int kSubBits = 8;
209:
210: static int GetLogSize(int size) {
211: for (int i = kSubBits; i < 32; i++)
212: for (int j = 0; j < (1 << kSubBits); j++)
213: if (size <= ((1) << i) + (j << (i - kSubBits)))
214: return (i << kSubBits) + j;
215: return (32 << kSubBits);
216: }
217:
218: static long MyMultDiv64(long value, long elapsedTime) {
219: long freq = 1000; // ms
220: long elTime = elapsedTime;
221: while (freq > 1000000) {
222: freq >>>= 1;
223: elTime >>>= 1;
224: }
225: if (elTime == 0)
226: elTime = 1;
227: return value * freq / elTime;
228: }
229:
230: static long GetCompressRating(int dictionarySize, long elapsedTime,
231: long size) {
232: long t = GetLogSize(dictionarySize) - (18 << kSubBits);
233: long numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits));
234: long numCommands = (size) * numCommandsForOne;
235: return MyMultDiv64(numCommands, elapsedTime);
236: }
237:
238: static long GetDecompressRating(long elapsedTime, long outSize,
239: long inSize) {
240: long numCommands = inSize * 220 + outSize * 20;
241: return MyMultDiv64(numCommands, elapsedTime);
242: }
243:
244: static long GetTotalRating(int dictionarySize, long elapsedTimeEn,
245: long sizeEn, long elapsedTimeDe, long inSizeDe,
246: long outSizeDe) {
247: return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) + GetDecompressRating(
248: elapsedTimeDe, inSizeDe, outSizeDe)) / 2;
249: }
250:
251: static void PrintValue(long v) {
252: String s = "";
253: s += v;
254: for (int i = 0; i + s.length() < 6; i++)
255: System.out.print(" ");
256: System.out.print(s);
257: }
258:
259: static void PrintRating(long rating) {
260: PrintValue(rating / 1000000);
261: System.out.print(" MIPS");
262: }
263:
264: static void PrintResults(int dictionarySize, long elapsedTime,
265: long size, boolean decompressMode, long secondSize) {
266: long speed = MyMultDiv64(size, elapsedTime);
267: PrintValue(speed / 1024);
268: System.out.print(" KB/s ");
269: long rating;
270: if (decompressMode)
271: rating = GetDecompressRating(elapsedTime, size, secondSize);
272: else
273: rating = GetCompressRating(dictionarySize, elapsedTime,
274: size);
275: PrintRating(rating);
276: }
277:
278: static public int LzmaBenchmark(int numIterations,
279: int dictionarySize) throws Exception {
280: if (numIterations <= 0)
281: return 0;
282: if (dictionarySize < (1 << 18)) {
283: System.out
284: .println("\nError: dictionary size for benchmark must be >= 18 (256 KB)");
285: return 1;
286: }
287: System.out
288: .print("\n Compressing Decompressing\n\n");
289:
290: SevenZip.Compression.lzma.Encoder encoder = new SevenZip.Compression.lzma.Encoder();
291: SevenZip.Compression.lzma.Decoder decoder = new SevenZip.Compression.lzma.Decoder();
292:
293: if (!encoder.SetDictionarySize(dictionarySize))
294: throw new Exception("Incorrect dictionary size");
295:
296: int kBufferSize = dictionarySize + kAdditionalSize;
297: int kCompressedBufferSize = (kBufferSize / 2)
298: + kCompressedAdditionalSize;
299:
300: ByteArrayOutputStream propStream = new ByteArrayOutputStream();
301: encoder.WriteCoderProperties(propStream);
302: byte[] propArray = propStream.toByteArray();
303: decoder.SetDecoderProperties(propArray);
304:
305: CBenchRandomGenerator rg = new CBenchRandomGenerator();
306:
307: rg.Set(kBufferSize);
308: rg.Generate();
309: CRC crc = new CRC();
310: crc.Init();
311: crc.Update(rg.Buffer, 0, rg.BufferSize);
312:
313: CProgressInfo progressInfo = new CProgressInfo();
314: progressInfo.ApprovedStart = dictionarySize;
315:
316: long totalBenchSize = 0;
317: long totalEncodeTime = 0;
318: long totalDecodeTime = 0;
319: long totalCompressedSize = 0;
320:
321: MyInputStream inStream = new MyInputStream(rg.Buffer,
322: rg.BufferSize);
323:
324: byte[] compressedBuffer = new byte[kCompressedBufferSize];
325: MyOutputStream compressedStream = new MyOutputStream(
326: compressedBuffer);
327: CrcOutStream crcOutStream = new CrcOutStream();
328: MyInputStream inputCompressedStream = null;
329: int compressedSize = 0;
330: for (int i = 0; i < numIterations; i++) {
331: progressInfo.Init();
332: inStream.reset();
333: compressedStream.reset();
334: encoder.Code(inStream, compressedStream, -1, -1,
335: progressInfo);
336: long encodeTime = System.currentTimeMillis()
337: - progressInfo.Time;
338:
339: if (i == 0) {
340: compressedSize = compressedStream.size();
341: inputCompressedStream = new MyInputStream(
342: compressedBuffer, compressedSize);
343: } else if (compressedSize != compressedStream.size())
344: throw (new Exception("Encoding error"));
345:
346: if (progressInfo.InSize == 0)
347: throw (new Exception("Internal ERROR 1282"));
348:
349: long decodeTime = 0;
350: for (int j = 0; j < 2; j++) {
351: inputCompressedStream.reset();
352: crcOutStream.Init();
353:
354: long outSize = kBufferSize;
355: long startTime = System.currentTimeMillis();
356: if (!decoder.Code(inputCompressedStream, crcOutStream,
357: outSize))
358: throw (new Exception("Decoding Error"));
359: ;
360: decodeTime = System.currentTimeMillis() - startTime;
361: if (crcOutStream.GetDigest() != crc.GetDigest())
362: throw (new Exception("CRC Error"));
363: }
364: long benchSize = kBufferSize - progressInfo.InSize;
365: PrintResults(dictionarySize, encodeTime, benchSize, false,
366: 0);
367: System.out.print(" ");
368: PrintResults(dictionarySize, decodeTime, kBufferSize, true,
369: compressedSize);
370: System.out.println();
371:
372: totalBenchSize += benchSize;
373: totalEncodeTime += encodeTime;
374: totalDecodeTime += decodeTime;
375: totalCompressedSize += compressedSize;
376: }
377: System.out
378: .println("---------------------------------------------------");
379: PrintResults(dictionarySize, totalEncodeTime, totalBenchSize,
380: false, 0);
381: System.out.print(" ");
382: PrintResults(dictionarySize, totalDecodeTime, kBufferSize
383: * (long) numIterations, true, totalCompressedSize);
384: System.out.println(" Average");
385: return 0;
386: }
387: }
|