JDK-8009548 : HttpServer and URLConnection introduce a 38 ms delay when using keep-alive
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.net
  • Affected Version: 6.0,7u15
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • Submitted: 2013-03-06
  • Updated: 2014-11-17
  • Resolved: 2014-05-20
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 8
8Resolved
Related Reports
Duplicate :  
Relates :  
Description
FULL PRODUCT VERSION :
java version  " 1.7.0_15 " 
Java(TM) SE Runtime Environment (build 1.7.0_15-b03)
Java HotSpot(TM) 64-Bit Server VM (build 23.7-b01, mixed mode)

or

java version  " 1.6.0_27 " 
OpenJDK Runtime Environment (IcedTea6 1.12.3) (6b27-1.12.3-0ubuntu1~12.04.1)
OpenJDK 64-Bit Server VM (build 20.0-b12, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
Linux i5 3.2.0-38-generic #61-Ubuntu SMP Tue Feb 19 12:18:21 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux


A DESCRIPTION OF THE PROBLEM :
HttpServer and URLConnection introduce a 38 ms delay when using keep-alive.


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
/**
 * @test
 * @bug
 * @summary  pipelining delay on Ubuntu 12.04.01 LTS / amd64
 */

import com.sun.net.httpserver.*;

import java.util.*;
import java.util.concurrent.*;
import java.io.*;
import java.net.*;

public class Bug {

    static int iterations = 20;
    static long requiredMinimumDelay = 10L;
    
    public static void main (String[] args) throws Exception {
        Handler handler = new Handler();
        InetSocketAddress addr = new InetSocketAddress (8075);
        HttpServer server = HttpServer.create (addr, 0);
        HttpContext ctx = server.createContext ( " /test " , handler);
        ExecutorService executor = Executors.newCachedThreadPool();
        server.setExecutor (executor);
        server.start ();

        long minDelay = requiredMinimumDelay * 1000L;
        
        try {
            for(int i = 0; i < iterations; i++) {
                URL url = new URL ( " http://localhost: " +server.getAddress().getPort()+ " /test/foo.html " );
                HttpURLConnection urlc = (HttpURLConnection)url.openConnection ();
                InputStream is = urlc.getInputStream();
                InputStreamReader isr = new InputStreamReader(is);
                BufferedReader br = new BufferedReader(isr);
                String res = br.readLine();
                br.close();
                
                // skip first few
                if(i < iterations/2) {
                    continue;
                }
                
                long delay = System.currentTimeMillis() - Long.parseLong(res);
                System.out.println( " delay:  " +delay+ "  ms " );
                if(delay < minDelay) {
                    minDelay = delay;
                }
            }
        } catch (Exception ex) {}
        
        server.stop(2);
        executor.shutdown();
        
        if(minDelay > requiredMinimumDelay) {
            throw new Exception( " minimum delay too large:  " +minDelay);
        }
    }

    static class Handler implements HttpHandler {
        public void handle (HttpExchange t)
            throws IOException
        {
            InputStream is = t.getRequestBody();
            Headers map = t.getRequestHeaders();
            Headers rmap = t.getResponseHeaders();
            while (is.read () != -1) ;
            is.close();
            String response = Long.toString(System.currentTimeMillis())+ " 
 " ;
            t.sendResponseHeaders (200, response.length());
            OutputStream os = t.getResponseBody();
            os.write (response.getBytes());
            t.close();
        }
    }
}


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

CUSTOMER SUBMITTED WORKAROUND :
Connection: close
Comments
Closing out as a duplicate given the 2013-05-09 comment.
20-05-2014

Issue (1) above is being handled via 8014254.
09-05-2013

This boils down to epoll_wait on Linux taking at least around 40 ms to report that a channel is readable, when a channel was readable before registering it will the selector. Since this is an OS issue, there is nothing we can do about it.
09-05-2013

There are essentially two problems reported here: (1) HttpServer induces a 1000 ms delay when using the keep-alive cache. The delay could be reduced to a lower number (maybe 100 ms). This delay is only noticeable if the server is single-threaded. This is a regression. (2) Linux systems have an additional 38-41 ms overhead. This delay is noticed when trying to read from the InputStream obtained from the HttpURLConnection to read the response. This is NOT a regression.
02-05-2013

See discussion: http://stackoverflow.com/questions/15235075/delay-in-httpserver-since-java-7
07-03-2013