Jay Roy
asked on
Analyzing thread profiling
hi guys
I have 11 threads(ThreadTaskExecutor ) running on a 2CPU (12 cores)
Attached is the screenshot of my threads.
Any idea what the 4 states mean (at the bottom right of the image)
Running
Sleeping
Wait
Monitor
From the screenshot it looks like most of the threads are in
Monitor state.
How can i improve the performance (increase / decrease number of threads ?)
Any help will be greatly appreciated
thanks
Threads.bmp
I have 11 threads(ThreadTaskExecutor
Attached is the screenshot of my threads.
Any idea what the 4 states mean (at the bottom right of the image)
Running
Sleeping
Wait
Monitor
From the screenshot it looks like most of the threads are in
Monitor state.
How can i improve the performance (increase / decrease number of threads ?)
Any help will be greatly appreciated
thanks
Threads.bmp
If you follow the diagram through you will see that 90% of the time, only 1 of your 11 threads are actually running at any point in time, and (as you said) the rest of the time they are in Monitor state. In case you don't know, Monitor state means that the thread is blocked waiting to get a hold of a lock (or monitor, hence the state's name).
So either your code uses an explicit Lock object or implicitly via "synchronized" methods it is manipulating locks, and in a way that will never be good for multithreaded execution, ie. no matter how many threads you allocate, more or less, it won't significantly change the performance. You need to look at the code that is being run to see why there is so much "lock contention".
Can you post the code?
So either your code uses an explicit Lock object or implicitly via "synchronized" methods it is manipulating locks, and in a way that will never be good for multithreaded execution, ie. no matter how many threads you allocate, more or less, it won't significantly change the performance. You need to look at the code that is being run to see why there is so much "lock contention".
Can you post the code?
ASKER
thanks
Its the screenshot from VisualVM profiler
Regarding the code:
My code is a single java process which executes a batch task.
The task is to select data from one table and insert it into another table.
Here is the snapshot of code
SPRING_CONFIG.xml
itemReader - SELECT COL1 as value1,COL2 as value2 from TABLE1
itemWriter - INSERT INTO TABLE2(COL1,COL2) values (:value1,:value2)
TABLE1 has 1 million rows
so the above process writes/inserts 1 million rows from TABLE1 to TABLE2
and this task is distributed among 11 threads.
I have a ProcessMain class with a main() which invokes the
above tasklet in SPRING_CONFIG.xml
So as you can see there is no synchronization being used.
Any idea how i can improve the performance.
The whole process takes more than 30 minutes,
thanks
Its the screenshot from VisualVM profiler
Regarding the code:
My code is a single java process which executes a batch task.
The task is to select data from one table and insert it into another table.
Here is the snapshot of code
SPRING_CONFIG.xml
<tasklet transaction-manager="transactionManager"
task-executor="threadTaskExecutor" throttle-limit="10">
<chunk reader="itemReader"
writer="itemWriter"
commit-interval="5000" />
</tasklet>
<beans:bean id="threadTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<beans:bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
p:dataSource-ref="dataSource" />
</beans:bean>
itemReader - SELECT COL1 as value1,COL2 as value2 from TABLE1
itemWriter - INSERT INTO TABLE2(COL1,COL2) values (:value1,:value2)
TABLE1 has 1 million rows
so the above process writes/inserts 1 million rows from TABLE1 to TABLE2
and this task is distributed among 11 threads.
I have a ProcessMain class with a main() which invokes the
above tasklet in SPRING_CONFIG.xml
public class ProcessMain{
public static void main(String args[]) {
ThreadPoolTaskExecutor threadPoolTaskExecutor = null;
ApplicationContext applicationContext = new ClassPathXmlApplicationContext(SPRING_CONFIG);
try {
threadPoolTaskExecutor = (ThreadPoolTaskExecutor) applicationContext.getBean("threadTaskExecutor");
threadPoolTaskExecutor.setCorePoolSize(11); //configure 11 threads
threadPoolTaskExecutor.setMaxPoolSize(12);
} catch (Exception e) {
logger.error("exception ..woohoo", e);
}
//invoke <tasklet> xml
}
}
So as you can see there is no synchronization being used.
Any idea how i can improve the performance.
The whole process takes more than 30 minutes,
thanks
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
little consufed now..if the readers and writers are not designed for multithreaded use
then why is there a option to use the ThreadpoolTaskExecutor
something like
i am doing something like
<step id="copyDataStep" next="nextTask">
<tasklet transaction-manager="trans actionMana ger"
task-executor="threadpooltaskexecutor" throttle-limit="10">
<beans:bean id="threadpooltaskexecutor"
class="org.springframework .schedulin g.concurre nt.ThreadP oolTaskExe cutor">
<property corepoolsize = "10" >
</beans:bean>
why is there a 'task-executor' option, do you know?
thanks.
then why is there a option to use the ThreadpoolTaskExecutor
something like
i am doing something like
<step id="copyDataStep" next="nextTask">
<tasklet transaction-manager="trans
task-executor="threadpooltaskexecutor" throttle-limit="10">
<beans:bean id="threadpooltaskexecutor"
class="org.springframework
<property corepoolsize = "10" >
</beans:bean>
why is there a 'task-executor' option, do you know?
thanks.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
>>In your case every thread is responsible to move all of the data from table1 to table2, it means that at the end the job is completed 11 times (by every thread).
that is not the case for me. so what you mean is since every thread is moving data from table1 to table2 there would be 11 million rows (one million by each thread)
but that is not the case, i see only one million in table2.
so in thoery what you said makes sense but practically that is not happening.
>>for example if you have to calculate sum of 100 elements in fastest way, and you have 10 threads, the first should sum 1-10, the second 11-20
how would you go about doing this ? I mean how would you assign
thread1 to sum 1-10
thread2 to sum 11-20
and so on..
Can you post some code ?
thx.
that is not the case for me. so what you mean is since every thread is moving data from table1 to table2 there would be 11 million rows (one million by each thread)
but that is not the case, i see only one million in table2.
so in thoery what you said makes sense but practically that is not happening.
>>for example if you have to calculate sum of 100 elements in fastest way, and you have 10 threads, the first should sum 1-10, the second 11-20
how would you go about doing this ? I mean how would you assign
thread1 to sum 1-10
thread2 to sum 11-20
and so on..
Can you post some code ?
thx.
Partitioning of the task is up to developer. Especially for partitioning of array you can check this article:
http://www.vogella.com/articles/JavaAlgorithmsPartitionCollection/article.html
it's a generic class that partitions a List to subLists.
http://www.vogella.com/articles/JavaAlgorithmsPartitionCollection/article.html
it's a generic class that partitions a List to subLists.
ASKER
hi Valeri and mccarl
I looked into the code and i take back my statement.
""So as you can see there is no synchronization being used"
Actually I am reading the data synchronously...so revisiting my code i have
<tasklet transaction-manager="trans actionMana ger"
task-executor="threadTaskE xecutor" throttle-limit="10">
<chunk reader="itemReader"
writer="itemWriter"
commit-interval="5000" />
</tasklet>
..
<beans:bean id="itemReader" parent="synchItemReader">
<beans:property name="delegate" ref="stageReader" />
</beans:bean>
<beans:bean id="synchItemReader" class="com.xmon.batch.Sync hItemReade r" abstract="true" />
package com.xmon.batch;
import org.springframework.batch. item.Execu tionContex t;
import org.springframework.batch. item.ItemR eader;
import org.springframework.batch. item.ItemS tream;
import org.springframework.batch. item.ItemS treamExcep tion;
import org.springframework.batch. item.NonTr ansientRes ourceExcep tion;
import org.springframework.batch. item.Parse Exception;
import org.springframework.batch. item.Unexp ectedInput Exception;
As you can see the read() which reads the data from the table is synchronized
so now i unserstand why so many threads are in monitor state.
Any sugesions on how i can improve the performance.
thanks.
I looked into the code and i take back my statement.
""So as you can see there is no synchronization being used"
Actually I am reading the data synchronously...so revisiting my code i have
<tasklet transaction-manager="trans
task-executor="threadTaskE
<chunk reader="itemReader"
writer="itemWriter"
commit-interval="5000" />
</tasklet>
..
<beans:bean id="itemReader" parent="synchItemReader">
<beans:property name="delegate" ref="stageReader" />
</beans:bean>
<beans:bean id="synchItemReader" class="com.xmon.batch.Sync
package com.xmon.batch;
import org.springframework.batch.
import org.springframework.batch.
import org.springframework.batch.
import org.springframework.batch.
import org.springframework.batch.
import org.springframework.batch.
import org.springframework.batch.
public class SynchItemReader<T> implements ItemReader<T>, ItemStream {
private ItemReader<T> delegate;
@Override
public synchronized T read() throws Exception, UnexpectedInputException,
ParseException, NonTransientResourceException {
return delegate.read();
}
public ItemReader<T> getDelegate() {
return delegate;
}
public void setDelegate(ItemReader<T> delegate) {
this.delegate = delegate;
}
}
As you can see the read() which reads the data from the table is synchronized
so now i unserstand why so many threads are in monitor state.
Any sugesions on how i can improve the performance.
thanks.
Any sugesions on how i can improve the performance.As we said earlier, probably the only way to increase performance is... for you to find some property of your data that will allow you to partition this process among the threads, ie. say you have an id column in this table with values from 1 - 1000000 for the 1 million rows that it stores, then you would partition the work so that the first thread does "select * from TABLE where id >= 1 and id <= 100000" and the second thread does "select * from TABLE where id >= 100001 and id <= 200000", etc, etc.
The link that I posted above mentions that Spring-Batch comes with an example (parallelJob) that sounds pretty much like what you are trying to do, so that might be a starting point.
It looks like only one thread is dedicated for your concurent thread pool.
If you have 12 cores it's the right decision to have 12 working threads, but it's difficult for me to understand why the picture is like this without the code.
read this article to understand how to utilize all of the CPU cores. It's short and very good:
http://embarcaderos.net/2011/01/23/parallel-processing-and-multi-core-utilization-with-java/
btw state 'monitor' is BLOCKED state, in which the thread is waiting to obtain a lock on an object, but it's not able to, because some other thread already hold this lock.