JDK-6437829 : java.net.URLEncoder.encode should be optimized for multi-threading
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 6
  • Priority: P3
  • Status: Closed
  • Resolution: Not an Issue
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2006-06-13
  • Updated: 2011-02-16
  • Resolved: 2006-10-27
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7
7Resolved
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.6.0-beta"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.6.0-beta-b59g)
Java HotSpot(TM) Client VM (build 1.6.0-beta-b59g, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

A DESCRIPTION OF THE PROBLEM :
java.net.URLEncoder.encode should not create a bottleneck in muti-threaded applications. We noticed that there is a severe bottleneck in the JDK library which results in extermely poor performance of java.net.Encoder.encode in muti-threaded applications under load.

I realized that there was a problem in the test I wrote for the second run. What happens in this case is that java.net.URLEncoder and apache codec are running at the same time. Even though the example represents more real life, it doesn't do apple to apple comparison. I did the test again by increasing iTests value to to 50000 and keeping the loop as original test.

   for(int i = 0; i < count; i++) {
     es.submit(getCall());
     start.countDown();
   }

In this case, java.net.Encoder was 3.2 slower than apache.  

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the following code provided here. You will need org.apache.commons.codec library to run this.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The sun's library is as good as apache commons codec.
ACTUAL -
JDK's java.net.Encoder.encode is even 90 time slower for initial threads.


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import org.apache.commons.codec.net.URLCodec;
import org.apache.commons.codec.EncoderException;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;

public class CodecTest {
  //private static URLCodec s_codec = new URLCodec();
  private static String s_encode = "This is a string for encoding!@#$%^&*()?<>;";

  public CodecTest() {
  }


  private String encodeSun(String str) throws UnsupportedEncodingException {
    return URLEncoder.encode(str, "UTF-8");
  }

  private String encodeApache(String str) throws EncoderException {
    URLCodec s_codec = new URLCodec("UTF-8");
    return s_codec.encode(str);
  }

  public void testSun(int iRuns) throws UnsupportedEncodingException {
    for(int i = 0; i < iRuns; i++) {
      encodeSun(s_encode + i);
    }
  }

  public void testApache(int iRuns) throws UnsupportedEncodingException, EncoderException {
    for(int i = 0; i < iRuns; i++) {
      encodeApache(s_encode + i);
    }

  }


  private static Callable getCall() {
    return new Callable() {
      public Object call() throws Exception {
        CodecTest test = new CodecTest();
        int iTests = 1000;
        String sSun = null;
        String sApache = null;
        start.await();
        //test sun
        long lStart = System.nanoTime();
        try {
          test.testSun(iTests);
        }
        catch(UnsupportedEncodingException e) {
          System.out.println("Unsupported encoding: " + e.getMessage());
        }
        long lEnd = System.nanoTime();
        long lSunTime = lEnd - lStart;

        barrier.await();

        //test apache commons codec
        lStart = System.nanoTime();
        try {

          test.testApache(iTests);
        }
        catch(UnsupportedEncodingException e) {
          System.out.println("Unsupported encoding: " + e.getMessage());
        }
        lEnd = System.nanoTime();
        long lApacheTime = lEnd - lStart;
        synchronized(lock) {
          System.out.println("Sun time: " + lSunTime / 1000000);
          System.out.println("Apache commons codec time: " + lApacheTime / 1000000);
          System.out.println("Apache commons codec is " + ((double) lSunTime / (double) lApacheTime) +
              " times faster than Sun");
        }
        end.countDown();
        return null;
      }
    };
  }
  public static final int count = 100;
  public static final Object lock = new Object();
  public static final CountDownLatch start = new CountDownLatch(count);
  public static final CountDownLatch end = new CountDownLatch(count);
  public static final CyclicBarrier barrier = new CyclicBarrier(count);
  public static void main(String[] args) throws Exception {
    ExecutorService es = Executors.newFixedThreadPool(count);
    for(int i = 0; i < count; i++) {
      es.submit(getCall());
      start.countDown();
    }
    end.await();
    es.shutdownNow();
  }
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Use org.apache.commons.codec.net.URLCodec

Comments
EVALUATION The times reported in the description section of this bug are before the fix for 6415062. Testing with Java SE 6 beta2 or greater I find that the performance of java.net.URLEncoder is comparable to org.apache.commons.codec.net.URLCodec, and in some cases better. It depends on the actual string being encoded and the encoding being used.
27-10-2006

EVALUATION We have already made significant improvements to this method, URLEncoder.encode, for mustang. We will look at this for the next release dolphin.
14-06-2006

EVALUATION There are already significant improvements to URLEncoder in beta2, through CR 6415062.
13-06-2006