Tomáš Zato
Tomáš Zato

Reputation: 53338

Short code to test HTTP latency?

There are some nice libraries like this from Apache, but that's little bit too complex for my purpose. All I need is to get the best estimate of HTTP latency (the time it takes to get connected with the server, regardless of transfer speed).

I tried the HTTP connection code from this answer:

  private void doPing() {
    //Remember time before connection
    long millis = System.currentTimeMillis();
    try (BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), "UTF-8"))) {
      //We don't need any data
      reader.close();
      //Times is the array where we store our results
      times.add((int)(System.currentTimeMillis()-millis));
      //I see lot's of these in console, so it's probably working
      System.out.println("Request done...");
    }
    //If internet is dead, does it throw exception?
    catch(Exception e) {
      times.add(-1);
    }
  }

The thing is that I am not so sure what am I measuring. Looping through the values gave me this results:

Testing connection to http://www.seznam.cz
      Threads: 5
      Loops per thread: 50
Given up waiting for results.
Average time to connection: 53.8 [ms]
Failures: 0.0%

Testing connection to http://www.seznam.cz
      Threads: 5
      Loops per thread: 100
Average time to connection: 43.58 [ms]
Failures: 0.0%

Testing connection to http://www.seznam.cz
      Threads: 5
      Loops per thread: 400
Average time to connection: 30.145 [ms]
Failures: 0.0%

Testing connection to http://www.stackoverflow.com
      Threads: 5
      Loops per thread: 30
Given up waiting for results.
Average time to connection: 4006.1111111111113 [ms]
Failures: 0.0%

Testing connection to http://www.stackoverflow.com
      Threads: 5
      Loops per thread: 80
Given up waiting for results.
Average time to connection: 2098.695652173913 [ms]
Failures: 0.0%

Testing connection to http://www.stackoverflow.com
      Threads: 5
      Loops per thread: 200
Given up waiting for results.
Average time to connection: 0.0 [ms]
//Whoops, connection dropped again
Failures: 100.0%

//Some random invalid url
Testing connection to http://www.sdsfdser.tk/
      Threads: 4
      Loops per thread: 20
Average time to connection: 0.0 [ms]
Failures: 100.0%

Not only that I am not so sure if I calculated what I wanted (though it reflects my experience), I am also not sure what happes in non standard cases.

While keeping in mind that this project is supposed to be simple and lightweight, could you tell me if I'm doing it right?

Upvotes: 3

Views: 3647

Answers (1)

dddsnn
dddsnn

Reputation: 2491

I think hailin suggested you create a raw Socket and connect it to the server instead of using URLConnection. I tried both, and I'm getting much higher latency with your version. I think opening a URLConnection must be doing some additional stuff in the background, though I'm not sure what.

Anyway, here's the version using a Socket (add exception handling as needed):

Socket s = new Socket();
SocketAddress a = new InetSocketAddress("www.google.com", 80);
int timeoutMillis = 2000;
long start = System.currentTimeMillis();
try {
    s.connect(a, timeoutMillis);
} catch (SocketTimeoutException e) {
    // timeout
} catch (IOException e) {
    // some other exception
}
long stop = System.currentTimeMillis();
times.add(stop - start);
try {
    s.close();
} catch (IOException e) {
    // closing failed
}

This resolves the hostname (www.google.com in the example), establishes a TCP connection on port 80 and adds the milliseconds it took to times. If you don't want the time for the DNS resolution in there, you can create an InetAddress with InetAddress.getByName("hostname") before you start the timer and pass that to the InetSocketAddress constructor.

Edit: InetSocketAddress's constructor also resolves the host name right away, so constructing it from a resolved ip address shouldn't make a difference.

Upvotes: 1

Related Questions