I need to execute up to 10 HTTP Post operations as quickly as possible. All posts are to the same destination, and to simplify things you can assume they are all doing the same operation, for now. Every millisecond counts. Executing a single HTTP post operation typically takes 50ms when executed as part of the main code, without any threads:
long start = System.currentTimeMillis( );
response = httpClient.execute(httppost, context);
long end = System.currentTimeMillis( );
long diff = end - start;
System.out.println(Thread.currentThread().getName() + ": Difference is: " + diff);
But to do a few at a time, I create a Thread per HTTP post operation, and pass each thread the same HttpClient object, complete with PoolingHttpClientConnectionManager:
protected HttpClient createHttpClient() {
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
cm.setMaxTotal(20);
cm.setDefaultMaxPerRoute(24);
RequestConfig.Builder requestBuilder = RequestConfig.custom();
requestBuilder = requestBuilder.setConnectTimeout(5000);
requestBuilder = requestBuilder.setSocketTimeout(5000);
HttpClientBuilder builder = HttpClientBuilder.create();
builder.setDefaultRequestConfig(requestBuilder.build());
builder.setConnectionManager(cm);
return builder.build();
}
CloseableHttpClient httpClient = (CloseableHttpClient) createHttpClient();
HttpParams httpParams = new DefaultHttpClient().getParams();
Runnable threadJob = new MyRunnable(httpClient, post);
Thread one = new Thread(threadJob);
Thread two = new Thread(threadJob);
Thread three = new Thread(threadJob);
Thread four = new Thread(threadJob);
Thread five = new Thread(threadJob);
Thread six = new Thread(threadJob);
Thread seven = new Thread(threadJob);
Thread eight = new Thread(threadJob);
Thread nine = new Thread(threadJob);
Thread ten = new Thread(threadJob);
one.start();
two.start();
three.start();
four.start();
five.start();
six.start();
seven.start();
eight.start();
nine.start();
ten.start();
Within the MyRunnable class, the same 50ms operation seems to take a good bit longer. Note I am not including the overhead of creating the thread etc in my metrics – I expect that to add to the overall time, but what’s perplexing me is why the same httpclient.execute() operation takes longer inside a thread, than it would be outside it. Inside MyRunnable's run() method:
long start = System.currentTimeMillis( );
response = httpClient.execute(httppost, context);
long end = System.currentTimeMillis( );
long diff = end - start;
System.out.println(Thread.currentThread().getName() + ": Difference is: " + diff);
My machine has 2 cores but 4 logical processors.
If I execute 4 threads, the times logged are typically like this:
58ms 155ms 160ms 179ms
It is consistently like this for ‘n’ threads – the first thread to complete registers a time slightly longer than ‘par’ time of 50ms, then the remainder all take around 3 times as long. Another typical result set for 10 threads:
52ms 156ms 156ms 160ms 156ms 161ms 175ms 158ms 176ms 178ms
Questions:
Is my ‘before and after’ logging method a reliable method of how long it takes?
Is this just the way it is when executing an http post operation inside a thread, or is there anything I can do to bring the average time down? (short of buying a more powerful machine).