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.

+3


source to share


1 answer


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.

+1


source







All Articles