1 package SevenZip; 2 3 import java.io.ByteArrayOutputStream; 4 import java.io.ByteArrayInputStream; 5 import java.io.IOException; 6 7 public class LzmaBench 8 { 9 static final int kAdditionalSize = (1 << 21); 10 static final int kCompressedAdditionalSize = (1 << 10); 11 12 static class CRandomGenerator 13 { 14 int A1; 15 int A2; CRandomGenerator()16 public CRandomGenerator() { Init(); } Init()17 public void Init() { A1 = 362436069; A2 = 521288629; } GetRnd()18 public int GetRnd() 19 { 20 return 21 ((A1 = 36969 * (A1 & 0xffff) + (A1 >>> 16)) << 16) ^ 22 ((A2 = 18000 * (A2 & 0xffff) + (A2 >>> 16))); 23 } 24 }; 25 26 static class CBitRandomGenerator 27 { 28 CRandomGenerator RG = new CRandomGenerator(); 29 int Value; 30 int NumBits; Init()31 public void Init() 32 { 33 Value = 0; 34 NumBits = 0; 35 } GetRnd(int numBits)36 public int GetRnd(int numBits) 37 { 38 int result; 39 if (NumBits > numBits) 40 { 41 result = Value & ((1 << numBits) - 1); 42 Value >>>= numBits; 43 NumBits -= numBits; 44 return result; 45 } 46 numBits -= NumBits; 47 result = (Value << numBits); 48 Value = RG.GetRnd(); 49 result |= Value & (((int)1 << numBits) - 1); 50 Value >>>= numBits; 51 NumBits = 32 - numBits; 52 return result; 53 } 54 }; 55 56 static class CBenchRandomGenerator 57 { 58 CBitRandomGenerator RG = new CBitRandomGenerator(); 59 int Pos; 60 int Rep0; 61 62 public int BufferSize; 63 public byte[] Buffer = null; 64 CBenchRandomGenerator()65 public CBenchRandomGenerator() { } Set(int bufferSize)66 public void Set(int bufferSize) 67 { 68 Buffer = new byte[bufferSize]; 69 Pos = 0; 70 BufferSize = bufferSize; 71 } GetRndBit()72 int GetRndBit() { return RG.GetRnd(1); } GetLogRandBits(int numBits)73 int GetLogRandBits(int numBits) 74 { 75 int len = RG.GetRnd(numBits); 76 return RG.GetRnd((int)len); 77 } GetOffset()78 int GetOffset() 79 { 80 if (GetRndBit() == 0) 81 return GetLogRandBits(4); 82 return (GetLogRandBits(4) << 10) | RG.GetRnd(10); 83 } GetLen1()84 int GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); } GetLen2()85 int GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); } Generate()86 public void Generate() 87 { 88 RG.Init(); 89 Rep0 = 1; 90 while (Pos < BufferSize) 91 { 92 if (GetRndBit() == 0 || Pos < 1) 93 Buffer[Pos++] = (byte)(RG.GetRnd(8)); 94 else 95 { 96 int len; 97 if (RG.GetRnd(3) == 0) 98 len = 1 + GetLen1(); 99 else 100 { 101 do 102 Rep0 = GetOffset(); 103 while (Rep0 >= Pos); 104 Rep0++; 105 len = 2 + GetLen2(); 106 } 107 for (int i = 0; i < len && Pos < BufferSize; i++, Pos++) 108 Buffer[Pos] = Buffer[Pos - Rep0]; 109 } 110 } 111 } 112 }; 113 114 static class CrcOutStream extends java.io.OutputStream 115 { 116 public CRC CRC = new CRC(); 117 Init()118 public void Init() 119 { 120 CRC.Init(); 121 } GetDigest()122 public int GetDigest() 123 { 124 return CRC.GetDigest(); 125 } write(byte[] b)126 public void write(byte[] b) 127 { 128 CRC.Update(b); 129 } write(byte[] b, int off, int len)130 public void write(byte[] b, int off, int len) 131 { 132 CRC.Update(b, off, len); 133 } write(int b)134 public void write(int b) 135 { 136 CRC.UpdateByte(b); 137 } 138 }; 139 140 static class MyOutputStream extends java.io.OutputStream 141 { 142 byte[] _buffer; 143 int _size; 144 int _pos; 145 MyOutputStream(byte[] buffer)146 public MyOutputStream(byte[] buffer) 147 { 148 _buffer = buffer; 149 _size = _buffer.length; 150 } 151 reset()152 public void reset() 153 { 154 _pos = 0; 155 } 156 write(int b)157 public void write(int b) throws IOException 158 { 159 if (_pos >= _size) 160 throw new IOException("Error"); 161 _buffer[_pos++] = (byte)b; 162 } 163 size()164 public int size() 165 { 166 return _pos; 167 } 168 }; 169 170 static class MyInputStream extends java.io.InputStream 171 { 172 byte[] _buffer; 173 int _size; 174 int _pos; 175 MyInputStream(byte[] buffer, int size)176 public MyInputStream(byte[] buffer, int size) 177 { 178 _buffer = buffer; 179 _size = size; 180 } 181 reset()182 public void reset() 183 { 184 _pos = 0; 185 } 186 read()187 public int read() 188 { 189 if (_pos >= _size) 190 return -1; 191 return _buffer[_pos++] & 0xFF; 192 } 193 }; 194 195 static class CProgressInfo implements ICodeProgress 196 { 197 public long ApprovedStart; 198 public long InSize; 199 public long Time; Init()200 public void Init() 201 { InSize = 0; } SetProgress(long inSize, long outSize)202 public void SetProgress(long inSize, long outSize) 203 { 204 if (inSize >= ApprovedStart && InSize == 0) 205 { 206 Time = System.currentTimeMillis(); 207 InSize = inSize; 208 } 209 } 210 } 211 static final int kSubBits = 8; 212 GetLogSize(int size)213 static int GetLogSize(int size) 214 { 215 for (int i = kSubBits; i < 32; i++) 216 for (int j = 0; j < (1 << kSubBits); j++) 217 if (size <= ((1) << i) + (j << (i - kSubBits))) 218 return (i << kSubBits) + j; 219 return (32 << kSubBits); 220 } 221 MyMultDiv64(long value, long elapsedTime)222 static long MyMultDiv64(long value, long elapsedTime) 223 { 224 long freq = 1000; // ms 225 long elTime = elapsedTime; 226 while (freq > 1000000) 227 { 228 freq >>>= 1; 229 elTime >>>= 1; 230 } 231 if (elTime == 0) 232 elTime = 1; 233 return value * freq / elTime; 234 } 235 GetCompressRating(int dictionarySize, long elapsedTime, long size)236 static long GetCompressRating(int dictionarySize, long elapsedTime, long size) 237 { 238 long t = GetLogSize(dictionarySize) - (18 << kSubBits); 239 long numCommandsForOne = 1060 + ((t * t * 10) >> (2 * kSubBits)); 240 long numCommands = (long)(size) * numCommandsForOne; 241 return MyMultDiv64(numCommands, elapsedTime); 242 } 243 GetDecompressRating(long elapsedTime, long outSize, long inSize)244 static long GetDecompressRating(long elapsedTime, long outSize, long inSize) 245 { 246 long numCommands = inSize * 220 + outSize * 20; 247 return MyMultDiv64(numCommands, elapsedTime); 248 } 249 GetTotalRating( int dictionarySize, long elapsedTimeEn, long sizeEn, long elapsedTimeDe, long inSizeDe, long outSizeDe)250 static long GetTotalRating( 251 int dictionarySize, 252 long elapsedTimeEn, long sizeEn, 253 long elapsedTimeDe, 254 long inSizeDe, long outSizeDe) 255 { 256 return (GetCompressRating(dictionarySize, elapsedTimeEn, sizeEn) + 257 GetDecompressRating(elapsedTimeDe, inSizeDe, outSizeDe)) / 2; 258 } 259 PrintValue(long v)260 static void PrintValue(long v) 261 { 262 String s = ""; 263 s += v; 264 for (int i = 0; i + s.length() < 6; i++) 265 System.out.print(" "); 266 System.out.print(s); 267 } 268 PrintRating(long rating)269 static void PrintRating(long rating) 270 { 271 PrintValue(rating / 1000000); 272 System.out.print(" MIPS"); 273 } 274 PrintResults( int dictionarySize, long elapsedTime, long size, boolean decompressMode, long secondSize)275 static void PrintResults( 276 int dictionarySize, 277 long elapsedTime, 278 long size, 279 boolean decompressMode, long secondSize) 280 { 281 long speed = MyMultDiv64(size, elapsedTime); 282 PrintValue(speed / 1024); 283 System.out.print(" KB/s "); 284 long rating; 285 if (decompressMode) 286 rating = GetDecompressRating(elapsedTime, size, secondSize); 287 else 288 rating = GetCompressRating(dictionarySize, elapsedTime, size); 289 PrintRating(rating); 290 } 291 LzmaBenchmark(int numIterations, int dictionarySize)292 static public int LzmaBenchmark(int numIterations, int dictionarySize) throws Exception 293 { 294 if (numIterations <= 0) 295 return 0; 296 if (dictionarySize < (1 << 18)) 297 { 298 System.out.println("\nError: dictionary size for benchmark must be >= 18 (256 KB)"); 299 return 1; 300 } 301 System.out.print("\n Compressing Decompressing\n\n"); 302 303 SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); 304 SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); 305 306 if (!encoder.SetDictionarySize(dictionarySize)) 307 throw new Exception("Incorrect dictionary size"); 308 309 int kBufferSize = dictionarySize + kAdditionalSize; 310 int kCompressedBufferSize = (kBufferSize / 2) + kCompressedAdditionalSize; 311 312 ByteArrayOutputStream propStream = new ByteArrayOutputStream(); 313 encoder.WriteCoderProperties(propStream); 314 byte[] propArray = propStream.toByteArray(); 315 decoder.SetDecoderProperties(propArray); 316 317 CBenchRandomGenerator rg = new CBenchRandomGenerator(); 318 319 rg.Set(kBufferSize); 320 rg.Generate(); 321 CRC crc = new CRC(); 322 crc.Init(); 323 crc.Update(rg.Buffer, 0, rg.BufferSize); 324 325 CProgressInfo progressInfo = new CProgressInfo(); 326 progressInfo.ApprovedStart = dictionarySize; 327 328 long totalBenchSize = 0; 329 long totalEncodeTime = 0; 330 long totalDecodeTime = 0; 331 long totalCompressedSize = 0; 332 333 MyInputStream inStream = new MyInputStream(rg.Buffer, rg.BufferSize); 334 335 byte[] compressedBuffer = new byte[kCompressedBufferSize]; 336 MyOutputStream compressedStream = new MyOutputStream(compressedBuffer); 337 CrcOutStream crcOutStream = new CrcOutStream(); 338 MyInputStream inputCompressedStream = null; 339 int compressedSize = 0; 340 for (int i = 0; i < numIterations; i++) 341 { 342 progressInfo.Init(); 343 inStream.reset(); 344 compressedStream.reset(); 345 encoder.Code(inStream, compressedStream, -1, -1, progressInfo); 346 long encodeTime = System.currentTimeMillis() - progressInfo.Time; 347 348 if (i == 0) 349 { 350 compressedSize = compressedStream.size(); 351 inputCompressedStream = new MyInputStream(compressedBuffer, compressedSize); 352 } 353 else if (compressedSize != compressedStream.size()) 354 throw (new Exception("Encoding error")); 355 356 if (progressInfo.InSize == 0) 357 throw (new Exception("Internal ERROR 1282")); 358 359 long decodeTime = 0; 360 for (int j = 0; j < 2; j++) 361 { 362 inputCompressedStream.reset(); 363 crcOutStream.Init(); 364 365 long outSize = kBufferSize; 366 long startTime = System.currentTimeMillis(); 367 if (!decoder.Code(inputCompressedStream, crcOutStream, outSize)) 368 throw (new Exception("Decoding Error"));; 369 decodeTime = System.currentTimeMillis() - startTime; 370 if (crcOutStream.GetDigest() != crc.GetDigest()) 371 throw (new Exception("CRC Error")); 372 } 373 long benchSize = kBufferSize - (long)progressInfo.InSize; 374 PrintResults(dictionarySize, encodeTime, benchSize, false, 0); 375 System.out.print(" "); 376 PrintResults(dictionarySize, decodeTime, kBufferSize, true, compressedSize); 377 System.out.println(); 378 379 totalBenchSize += benchSize; 380 totalEncodeTime += encodeTime; 381 totalDecodeTime += decodeTime; 382 totalCompressedSize += compressedSize; 383 } 384 System.out.println("---------------------------------------------------"); 385 PrintResults(dictionarySize, totalEncodeTime, totalBenchSize, false, 0); 386 System.out.print(" "); 387 PrintResults(dictionarySize, totalDecodeTime, 388 kBufferSize * (long)numIterations, true, totalCompressedSize); 389 System.out.println(" Average"); 390 return 0; 391 } 392 } 393