简体   繁体   中英

Long running multi threaded application runs 4x slower when deployed to tomcat than when run from command line

When I run this long running process from the command line it takes about 30 seconds to complete. When I deploy this same code to tomcat7 and call the same function from a simple Vaadin web application it takes almost 150 seconds. This is the time for a specific function to execute, not anything related to interface slowing it down.

Here's is a simple example that illustrates 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'm running this on has 48 available cores. When I run this code from the command line I get 48 threads running ~98% each. When I run it through tomcat each thread tops out at around 82-86% according to top. 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 thread 99%...

Does tomcat do something to limit this tread pool in some way, or have some additional overhead with threads that I am not aware of? Or is there a better way to multi-thread in this case? Some overhead is obviously acceptable, but something doesn't seem right here for it to take that much longer through tomcat.

Have you tried to ensure that the total number of threads that Tomcat and your jobs use totals the number of cores on your system? I would venture to say that you would probably get closer to the 99% execution for those threads.

The other question that I have is if the Tomcat threads have a higher priority than your worker threads. If that is the case then you should be seeing this difference on a consistent basis. I do not recall if you can see the thread priority using jconsole or visualvm but maybe increasing the thread priority of the thread pool should provide more cpu cycle but that will affect tomcat ability to handle web requests.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM