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; 16 public CRandomGenerator() { Init(); } 17 public void Init() { A1 = 362436069; A2 = 521288629; } 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; 31 public void Init() 32 { 33 Value = 0; 34 NumBits = 0; 35 } 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 65 public CBenchRandomGenerator() { } 66 public void Set(int bufferSize) 67 { 68 Buffer = new byte[bufferSize]; 69 Pos = 0; 70 BufferSize = bufferSize; 71 } 72 int GetRndBit() { return RG.GetRnd(1); } 73 int GetLogRandBits(int numBits) 74 { 75 int len = RG.GetRnd(numBits); 76 return RG.GetRnd((int)len); 77 } 78 int GetOffset() 79 { 80 if (GetRndBit() == 0) 81 return GetLogRandBits(4); 82 return (GetLogRandBits(4) << 10) | RG.GetRnd(10); 83 } 84 int GetLen1() { return RG.GetRnd(1 + (int)RG.GetRnd(2)); } 85 int GetLen2() { return RG.GetRnd(2 + (int)RG.GetRnd(2)); } 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 118 public void Init() 119 { 120 CRC.Init(); 121 } 122 public int GetDigest() 123 { 124 return CRC.GetDigest(); 125 } 126 public void write(byte[] b) 127 { 128 CRC.Update(b); 129 } 130 public void write(byte[] b, int off, int len) 131 { 132 CRC.Update(b, off, len); 133 } 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 146 public MyOutputStream(byte[] buffer) 147 { 148 _buffer = buffer; 149 _size = _buffer.length; 150 } 151 152 public void reset() 153 { 154 _pos = 0; 155 } 156 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 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 176 public MyInputStream(byte[] buffer, int size) 177 { 178 _buffer = buffer; 179 _size = size; 180 } 181 182 public void reset() 183 { 184 _pos = 0; 185 } 186 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; 200 public void Init() 201 { InSize = 0; } 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 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 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 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 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 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 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 269 static void PrintRating(long rating) 270 { 271 PrintValue(rating / 1000000); 272 System.out.print(" MIPS"); 273 } 274 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 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