Link to home
Start Free TrialLog in
Avatar of Jay Roy
Jay RoyFlag for United States of America

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
Avatar of Valeri
Valeri
Flag of Bulgaria image

is it screenshot from JProfiler?
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.
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?
Avatar of Jay Roy

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

<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>

Open in new window



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
}
}

Open in new window


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
Avatar of mccarl
mccarl
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Jay Roy

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="transactionManager"
task-executor="threadpooltaskexecutor" throttle-limit="10">

<beans:bean id="threadpooltaskexecutor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property corepoolsize = "10" >
</beans:bean>

why is there a 'task-executor' option, do  you know?

thanks.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Jay Roy

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.
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.
Avatar of Jay Roy

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="transactionManager"
task-executor="threadTaskExecutor" 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.SynchItemReader" abstract="true" />

package com.xmon.batch;

import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemReader;
import org.springframework.batch.item.ItemStream;
import org.springframework.batch.item.ItemStreamException;
import org.springframework.batch.item.NonTransientResourceException;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;

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;
	}

}

Open in new window


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.