0

Below code tests the response time of reading www.google.com into a BufferedReader. I plan on using this code to test the response times of other sites and web services within intranet. Below tests runs for 20 seconds and opens 4 requests per second :

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.junit.Test;

public class ResponseTimeTest {

    private static final int NUMBER_REQUESTS_PER_SECOND = 4;
    private static final int TEST_EXECUTION_TIME = 20000;
    private static final ConcurrentHashMap<Long, Long> timingMap = new ConcurrentHashMap<Long, Long>();

    @Test
    public void testResponseTime() throws InterruptedException {

        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(10);
        scheduler.scheduleAtFixedRate(new RequestThreadCreator(), 0, 1, TimeUnit.SECONDS);      
        Thread.sleep(TEST_EXECUTION_TIME);

        System.out.println("Start Time, End Time, Total Time");
        for (Entry<Long, Long> entry : timingMap.entrySet())
        {
            System.out.println(entry.getKey() + "," + entry.getValue() +","+(entry.getValue() - entry.getKey()));
        }


    }

    private final class RequestThreadCreator implements Runnable {

        public void run() {

            ExecutorService es = Executors.newCachedThreadPool();

            for (int i = 1; i <= NUMBER_REQUESTS_PER_SECOND; i++) {
                es.execute(new RequestThread());
            }
            es.shutdown();

        }
    }

    private final class RequestThread implements Runnable {

        public void run() {

            long startTime = System.currentTimeMillis();
            try {
                URL oracle = new URL("http://www.google.com/");
                URLConnection yc = oracle.openConnection();
                BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()));

                while ((in.readLine()) != null) {
                }
                in.close();

            } catch (Exception e) {
                e.printStackTrace();
            }
            long endTime = System.currentTimeMillis();
            timingMap.put(startTime, endTime);
        }
    }

}

The output is :

Start Time, End Time, Total Time
1417692221531,1417692221956,425
1417692213530,1417692213869,339
1417692224530,1417692224983,453
1417692210534,1417692210899,365
1417692214530,1417692214957,427
1417692220530,1417692221041,511
1417692209530,1417692209949,419
1417692215532,1417692215950,418
1417692214533,1417692215075,542
1417692213531,1417692213897,366
1417692212530,1417692212924,394
1417692219530,1417692219897,367
1417692226532,1417692226876,344
1417692211530,1417692211955,425
1417692209529,1417692209987,458
1417692222531,1417692222967,436
1417692215533,1417692215904,371
1417692219531,1417692219954,423
1417692215530,1417692215870,340
1417692217531,1417692218035,504
1417692207547,1417692207882,335
1417692208535,1417692208898,363
1417692207544,1417692208095,551
1417692208537,1417692208958,421
1417692226533,1417692226899,366
1417692224531,1417692224951,420
1417692225529,1417692225957,428
1417692216530,1417692216963,433
1417692223541,1417692223884,343
1417692223546,1417692223959,413
1417692222530,1417692222954,424
1417692208532,1417692208871,339
1417692207536,1417692207988,452
1417692226538,1417692226955,417
1417692220531,1417692220992,461
1417692209531,1417692209953,422
1417692226531,1417692226959,428
1417692217532,1417692217944,412
1417692210533,1417692210964,431
1417692221530,1417692221870,340
1417692216531,1417692216959,428
1417692207535,1417692208021,486
1417692223548,1417692223957,409
1417692216532,1417692216904,372
1417692214535,1417692215071,536
1417692217530,1417692217835,305
1417692213529,1417692213954,425
1417692210531,1417692210964,433
1417692212529,1417692212993,464
1417692213532,1417692213954,422
1417692215531,1417692215957,426
1417692210529,1417692210868,339
1417692218531,1417692219102,571
1417692225530,1417692225907,377
1417692208536,1417692208966,430
1417692218533,1417692219168,635

As System.out.println is synchronized in order to not skew results I add the timings to a ConcurrentHashMap and do not output the timings within the RequestThread itself. Are other gotcha's I should be aware of in above code so as to not skew the results. Or are there area's I should concentrate on in order to improve the accuracy or is it accurate "enough", by enough accurate to approx 100 millliseconds.

blue-sky
  • 51,962
  • 152
  • 427
  • 752
  • Just an opinion, you should use JMeter to test this. – Luke SpringWalker Dec 04 '14 at 16:53
  • Gotcha: `timingMap.put(startTime,...` -- `startTime` quite likely to have same value in different threads (esp., if you run this more than once), you better have your map keyed by some unique id (atomic integer will do) and hold values of `start, end` pairs. – Victor Sorokin Dec 05 '14 at 17:53
  • @VictorSorokin why would timing map contain same value in different threads ? accessing System.currentTimeMillis() does not modify state so is thread safe ? – blue-sky Dec 05 '14 at 23:28
  • And why can not? Your threads will call it during same millisecond, it's perfectly possible. – Victor Sorokin Dec 07 '14 at 11:25
  • @Victor Sorokin I accept two threads may invoke System.currentTimeMillis() at same time, but why is this an issue? If two threads invoke System.currentTimeMillis() then that is the correct start or end time for that thread, the startTime & endTime variables are contained within the thread so there should be no overlapping of state ? Are you saying System.currentTimeMillis() is not an atomic operation so a thread could modify its value while it is being read ? Also instead of atomic integer could use Thread.currentThread().getId()? – blue-sky Dec 10 '14 at 11:46
  • Since map is shared by threads, you can be getting one pair , whereas you must be have as many pairs as there were calls to `currentTime` at the same millisecond. – Victor Sorokin Dec 10 '14 at 16:21
  • @Victor Sorokin can you emulate this behavior in a small test/explain using code in an answer ? – blue-sky Dec 10 '14 at 16:39
  • Well you are mostly measuring how long it takes to decode the webpage, not the "responsiveness" of the webpage. –  Dec 23 '14 at 03:34

0 Answers0