In this blog,I'll test the coroutine supported on jvm,now famous is scala actor & kilim,this blog show the program reliazed with scala actor/kilim/java,let's compare these three program performance.
Test scene:
1.start cpu+1 threads;
2.these threads notify processor,repeat (cpu+1)*100 times,every time notify sleep random(5) ms;
3.processor asynchronous handle the message,the handler process is create a List(1000),and add element to this list,then sleep random(2) ms,repeat the process 100 times,then finish the processor.
Test Machine I: 2 core CPU(Intel(R) Xeon(R) CPU E5410 @ 2.33GHz) 1.5G memory
Test Env: JDK 1.6.0_07、linux kernel 2.6.9
Execute result:
1. java version: 8397ms cpu us: about 84% sy: about 8%
2. scala version: 12403ms cpu us: about 70% sy: about 13%
3. kilim version: 10959ms cpu us: about 70% sy: about 14%
Test Machine II: 8 core CPU(Intel(R) Xeon(R) CPU E5410 @ 2.33GHz) 4G memory
Test Env: JDK 1.6.0_14、linux kernel 2.6.9
Execute result:
1. java version: 36797ms cpu us: about 80% sy: about 3%
2. scala version: 19722ms cpu us: about 70% sy: about 1.5%
3. kilim version: 16008ms cpu us: about 85% sy: about 1.8%
Execute summary:
When cpu core and thread adds, scala & kilim performance will be better than java version, It show scala & kilim can use multicore cpu more effectivly, kilim performance sees better than scala in this scene.
If you have some tunning suggest,pls let me know,thks.
java version code:
public class MicroBenchmark {
private static final int processorCount=Runtime.getRuntime().availableProcessors()+1;
private static Processor processor=new Processor();
private static CountDownLatch latch=null;
private static Random random=new Random();
private static int executeTimes=processorCount*100;
public static void main(String[] args) throws Exception{
long beginTime=System.currentTimeMillis();
latch=new CountDownLatch(executeTimes*processorCount);
for (int j = 0; j < processorCount; j++) {
new Thread(new NotifyProcessorTask()).start();
}
latch.await();
long endTime=System.currentTimeMillis();
System.out.println("execute time: "+(endTime-beginTime)+" ms");
}
static class NotifyProcessorTask implements Runnable{
public void run() {
for (int i = 0; i < executeTimes; i++) {
processor.messageReceived(latch);
try {
Thread.sleep(random.nextInt(5));
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class Processor {
private static final int maxThread=(Runtime.getRuntime().availableProcessors()+1)*100;
private static ThreadPoolExecutor executor=null;
private Random random=new Random();
public Processor(){
executor=new ThreadPoolExecutor(10,maxThread,5,TimeUnit.SECONDS,new SynchronousQueue<Runnable>(),new ThreadPoolExecutor.AbortPolicy());
}
public void messageReceived(final CountDownLatch latch){
Runnable task=new Runnable(){
public void run() {
try {
handle();
}
catch (Exception e) {
e.printStackTrace();
}
latch.countDown();
}
};
executor.execute(task);
}
private void handle() throws Exception{
int counter=0;
while(counter<100){
List<String> list=new ArrayList<String>();
for (int i = 0; i < 1000; i++) {
list.add(String.valueOf(i));
}
counter++;
Thread.sleep(random.nextInt(2));
}
}
}
scala version code:
object MicroBenchmark {
val processorCount=Runtime.getRuntime.availableProcessors+1
val executeTimes=processorCount*100
def main(args : Array[String]) : Unit = {
val beginTime=System.currentTimeMillis
val latchCount=executeTimes*processorCount
var latch=new CountDownLatch(latchCount)
var i=0
while(i<processorCount){
new Thread(new NotifyProcessorTask(latch)).start
i+=1
}
latch.await()
val endTime=System.currentTimeMillis;
println("execute time: "+(endTime-beginTime)+"ms")
exit
}
}
class NotifyProcessorTask(latch:CountDownLatch) extends Runnable{
val executeTimes=(Runtime.getRuntime.availableProcessors+1)*100
val random=new Random
val actor=new Processor
def run() {
var i=0
actor.start
while(i < executeTimes){
actor ! TaskMessage.TaskExecuted(latch,0)
i+=1
Thread.sleep(random.nextInt(5))
}
}
}
abstract sealed class TaskMessage
object TaskMessage {
case class TaskExecuted(latch: CountDownLatch, counter:Int) extends TaskMessage
}
class Processor extends Actor{
var random=new Random
def act(){
loop {
react {
case TaskMessage.TaskExecuted(latch,counter) => handle(latch,counter)
}
}
}
def handle(latch: CountDownLatch,counter: Int){
val list=new Array[String](1000)
var i=0
for(i<-0 to 999){
list(i)=i.toString
}
var selfCounter=counter;
if(selfCounter<99){
selfCounter+=1
new Sleeper(random.nextInt(2),this,selfCounter,latch).start
}
else{
latch.countDown()
}
}
}
class Sleeper(time: Long, origin:Actor, counter:Int, latch:CountDownLatch) extends Actor {
def act() {
reactWithin(time) {
case TIMEOUT =>
origin ! TaskMessage.TaskExecuted(latch,counter)
}
}
}
kilim code version:
public class MicroBenchmark {
private static final int processorCount=Runtime.getRuntime().availableProcessors()+1;
private static CountDownLatch latch=null;
private static Random random=new Random();
private static int executeTimes=processorCount*100;
public static void main(String[] args) throws Exception{
long beginTime=System.currentTimeMillis();
latch=new CountDownLatch(executeTimes*processorCount);
for (int j = 0; j < processorCount; j++) {
new Thread(new NotifyProcessorTask()).start();
}
latch.await();
long endTime=System.currentTimeMillis();
System.out.println("execute time: "+(endTime-beginTime)+" ms");
System.exit(0);
}
static class NotifyProcessorTask implements Runnable{
public void run() {
String threadName=Thread.currentThread().getName();
for (int i = 0; i < executeTimes; i++) {
Mailbox<String> messages=new Mailbox<String>();
new Processor(messages,latch).start();
messages.putnb(threadName+String.valueOf(i));
try {
Thread.sleep(random.nextInt(5));
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public class Processor extends Task{
private Random random=new Random();
private Mailbox<String> messages;
private CountDownLatch latch;
public Processor(Mailbox<String> messages,CountDownLatch latch){
this.messages=messages;
this.latch=latch;
}
public void execute() throws Pausable, Exception {
messages.get();
int counter=0;
while(counter<100){
List<String> list=new ArrayList<String>();
for (int i = 0; i < 1000; i++) {
list.add(String.valueOf(i));
}
counter++;
Task.sleep(random.nextInt(2));
}
latch.countDown();
Task.exit(0);
}
}