Long running multithreaded application runs 4x slower when deployed to tomcat than when run from command line
When I run this lengthy process from the command line, it takes about 30 seconds to complete. When I deploy this same code in tomcat7 and call the same function from a simple Vaadin web app, it takes almost 150 seconds. This is the time to complete a specific function, not something to slow it down.
Here's a simple example to illustrate the problem:
public static void main(String[] args) {
try {
multiCounter(800);
} catch (InterruptedException | ExecutionException e) {e.printStackTrace();}
System.out.println("Completed");
}
public static void multiCounter(int numberOfCounters) throws InterruptedException, ExecutionException
{
//estimate the number of available processors
int maxNumberOfThreads = Runtime.getRuntime().availableProcessors();
//create thread pool and queue for future jobs
ExecutorService pool = Executors.newFixedThreadPool(maxNumberOfThreads);
ArrayList<Future<Integer>> futureJobs = new ArrayList<Future <Integer>>();
for(int index=0; index<numberOfCounters; index++)
{
Callable<Integer> callable = new dummyCalculator();
Future<Integer> future = pool.submit(callable);
futureJobs.add(future);
}
//placeholder for results
ArrayList <Integer> results= new ArrayList <Integer>(0);
//pull completed jobs from queue and extract results,
//adding to results container
for(Future<Integer> future : futureJobs)
{results.add(future.get());}
for(Integer res : results)
{System.out.println("Count:" + res);}
//close thread pool
pool.shutdown();
}
final static class dummyCalculator implements Callable<Integer>
{
@Override
public Integer call() throws Exception {
Integer counter = 0;
for(int p1Index=0; p1Index<800; p1Index++)
{
for(int p2Index=p1Index; p2Index<800; p2Index++)
{
for(int markerIndex=0; markerIndex<200; markerIndex++)
{counter++;}
}
}
return(counter);
}
}
The server I am running on has 48 cores available. When I run this code from the command line, I get 48 threads running at 98%. When I run it through tomcat, each thread reaches the top at 82-86%. If I decrease the number of threads in the code on tomcat the% per thread increases. 12 threads will get me 92% per thread. 1 stream 99% ...
Does tomcat help to limit this tread pool in any way or have some additional threading overhead that I am not aware of? Or is there a better way to multithread in this case? Some overhead is obviously acceptable, but something doesn't seem right here as it can take a lot longer through tomcat.
source to share
Have you tried to ensure that the total number of threads used by Tomcat and your jobs is equal to the number of cores on your system? I would venture to say that you are probably getting close to 99% performance for these threads.
Another question I have is that Tomcat threads have higher priority than your worker threads. If so, then you should see this distinction on an ongoing basis. I don't remember if you can see the priority of a thread using jconsole or visualvm, but perhaps increasing the priority of a thread pool thread should provide more cpu cycles, but it will affect tomcat's ability to handle web requests.
source to share