LzmaBench.java 9.3 KB

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