Code Review Request for # 6975829 : Perf. of gzip in existing JDKs is too slower than in 1.3.1

Xueming Shen xueming.shen at
Thu Sep 30 22:29:17 UTC 2010

  Martin, Alan

Please help review the change for #6975829 

This is again a problem triggered by the change we putback years ago for
6206933: GZipOutputStream/InputStream goes critical(calls 
JNI_Get*Critical) and causes slowness

in which we switch from using the JNI_Get*Critical to access the input bits
to using GetByteArrayregion(...) (which invloves array copy)

The test case attached in the bug report exaggeratedly use file size of the
.gz file as the buf size param for the GZIPInputStream() constructor.

         File f = new File(TESTFILE);
         DataInputStream dis = new DataInputStream(new 
GZIPInputStream(new FileInputStream(f), (int)f.length()))

and then start to read in the data in very small chunk via dis, which is 
a disaster.

While it is possible to workaround the issue easily by
a) to use a smaller buf size, such as the defualt 512
b) wrap the GZIPInputStream with a BufferedInputStream

It still appears the memory/buffer handling code in Inflater.c can be 
changed to improve
the performance in use cases similar to above mentioned scenario. The 
proposed change
is to copy no more than the size of the "user's buffer". It's an 
de-compression, so you can't
consume more bytes than you can write out in most cases. The attached 
test case shows
the performance of gzip-ing the un-compressed rt.jar by using different 
buffer size.

Again, we still need to address the "fundamental performance" issue 
caused by moving
away from JNI_Get*Critical for #6206933. But that will be a separate 


     private static int BUFSIZE = 1024 * 1024;

     public static void main(String[] args) throws Exception {

         File f = new File(args[0]);

         //gzip it into memory, yeah we have enough memoery:-)
         ByteArrayOutputStream baos = new 
ByteArrayOutputStream((int)f.length() / 2);
         GZIPOutputStream gout = new GZIPOutputStream(baos);
         FileInputStream in = new FileInputStream(args[0]);
         byte[] copyBuf = new byte[BUFSIZE];
         int n;
         while ((n = != -1) {
             gout.write(copyBuf, 0, n);

         byte[] gsrc = baos.toByteArray();

         for (int i = 1; i <= 128; i <<= 1 ) {
             copyBuf = new byte[BUFSIZE / i];
             long time = System.currentTimeMillis();
             for (int j = 0; j < 20; j++) {
                 ByteArrayInputStream bais = new ByteArrayInputStream(gsrc);
                 GZIPInputStream gin = new GZIPInputStream(bais, BUFSIZE);
                 while (( != -1) {}
             System.out.printf( "buf[1/%d]: %d ms%n", i, 
(System.currentTimeMillis() - time)/ 20);

(1) latest jdk7
sherman at sherman-linux:/home/sherman/TL/dis$  
/net/koori/onestop/jdk/7/latest/binaries/linux-i586/bin/java Inf /tmp/rt.jar
buf[1/1]: 579 ms
buf[1/2]: 640 ms
buf[1/4]: 613 ms
buf[1/8]: 683 ms
buf[1/16]: 873 ms
buf[1/32]: 1247 ms
buf[1/64]: 1958 ms
buf[1/128]: 3379 ms

(2) with proposed fix
sherman at sherman-linux:/home/sherman/TL/dis$ java Inf 
/tmp/rt.jarbuf[1/1]: 514 ms
buf[1/2]: 546 ms
buf[1/4]: 460 ms
buf[1/8]: 413 ms
buf[1/16]: 426 ms
buf[1/32]: 448 ms
buf[1/64]: 436 ms
buf[1/128]: 448 ms

More information about the core-libs-dev mailing list