1

I am currently using 5 threadpools and I want to find optimal sizing for these pools. This is some kind of prior analysis. Pools are divided by usage: for handling commands (cmdPool), handling inventory transactions (invPool), pool for database transactions (dbPool), also pool for common things that simply need to run async like I/O (fastPool) and for scheduled tasks (timerPool). I do not have any statistical data that could be used for solving problem yet.

For database query I am using HikariCP with default values. I will try to change count of maximum connections and minimum idle connections later to find optimal performance. But for now, when using Hikari pool it will be always called from one of the pools to not affect main thread. Usual database query is called under dbPool but only when code block is not part of already runnable submited into one of the thread pools.

Actual setup looks it just works right in application. So my questions are:

1.) How will impact performance and resources when I decide to stop using cachedThreadPool and use pool with some minimum idle threads like timerPool or I should stick with cached ?

2.) Is right solution to set a maximum pool size to prevent spikes when like 100 clients will join in small period of time and let them keep wait for some short time while other task will complete.

3.) Is there any better solution how to manage many kinds of tasks ?

cmdPool = Executors.newFixedThreadPool(3);
invPool = Executors.newFixedThreadPool(2);
dbPool = Executors.newCachedThreadPool();
fastPool = Executors.newCachedThreadPool();
timerPool = new ScheduledThreadPoolExecutor(5);
timerPool.allowCoreThreadTimeOut(true);
timerPool.setKeepAliveTime(3, TimeUnit.MINUTES); 

So first of all, every action depends on how many clients are connected, lets assume values like 5-25 clients. Pools should be designed to maintain even extremes like 100 clients and not make too many threads in small time period.

Expected uses may vary and are not same every second even may happen no task will come to run at all. Expected usage of cmdPool is like 3-8 uses per second (lightweight tasks). For invPool is usage nearly same like for cmdPool 2-6 uses per second (also lightweight tasks). As for dbPool this is more unpredictable than all others, but still expected usage is from 5-20 uses per second (lightweight and mediumweight tasks) also depends on how busy is network. Timer and fast pools are designed to take any kind of task and just do it, there is expected use of 20-50 uses per second.

I appreciate any suggestions, thank you.

Cycan
  • 13
  • 3

1 Answers1

0

The best solution is to adapt your application to the expected traffic. You can do that in many manners:

  • Design it with a microservice architecture leaving the orchestrator to handle peak of traffic
  • Design the application that reads the parameters of the size of thread pools on the fly (from a database from a file, from a configuration server...), so you can change the values when needed
  • If you need only to tune your application but you don't need to change the values on the fly put your configurations in a file (or database). Check different configurations to find the most adapted to your needs

What is important is to move away a code similar to this one:

cmdPool = Executors.newFixedThreadPool(3);

and replace it with a code similar to this one

@Value("${cmdPoolSize}")
private int cmdPoolSize;

...

cmdPool = Executors.newFixedThreadPool(cmdPoolSize);

where the size of the pool is not taken from the code, but from an external configuration.

A better way is also to define the kind of pool with parameters:

@Value("${cmdPoolType}")
private String cmtPoolType;

@Value("${cmdPoolSize}")
private int cmdPoolSize;

...

if (cmdPoolType.equals("cached")) {
  cmdPool = Executors.newCachedThreadPool();
} else if (cmdPoolType.equals("fixed")) {
  cmdPool = Executors.newFixedThreadPool(cmdPoolSize);  
}

Where you choose the reasonable kind of available pools.

In this last case you can also use a spring configuration file and change it before starting the application.

Davide Lorenzo MARINO
  • 26,420
  • 4
  • 39
  • 56