協程和線程性能測試

這裏測試使用的是協程的quasar框架。

代碼使用CountDownLatch對線程進行控制,分別檢測其創建和運行時間。

時間測試:

設想以下的場景,使用15個線程來調用某加了同步鎖的方法,每次這個方法的執行時間在25ms左右,那線程和協程都需要多少時間完成方法調用:

線程:

         創建時間:2-3ms

         運行時間:375ms

協程:

         創建時間:150ms

         運行時間:375ms

可以發現協程的創建要比線程的創建花費更多的時間。

 

cpu佔用測試:

另外從cup的佔用角度來分析兩者的區別,因爲375ms太短,所以將線程數改爲150來測試:

 

上圖的左側是協程運行的情況,右側是線程運行的情況,總的來說,協程運行的cup佔用峯值要比線程小,但持續時間比線程長。所以其實對一些長時間執行的任務,協程的運行開銷應該比線程小一些。

 

去掉同步鎖的情況:

另外協程對線程的優勢應該上下文切換頻繁的場景,所以不用鎖的情況可能協程的運行效率更高,將同步鎖去掉繼續測試:

發現在線程數在150以上的情況下,協程的運行時間要比線程短,且隨着線程數的增長,這種差距會增大。

 

總結:

所以總的來說,平時的場景時不太需要協程的,只有在線程常駐內存來處理長任務時,或是在需要大量線程來併發的時候,協程的效率會比線程高。對於一些短的任務,併發較少的情況,線程反而更具優勢。

 

測試代碼:

線程:

/**
 * @Auther: muyu
 * @Date: 2018-10-09-16:33
 */
import java.util.concurrent.CountDownLatch;

    class service{
         public void sleeps(CountDownLatch endGate, CountDownLatch startGate){
            try {
                startGate.await();
                Thread.sleep(25);
                System.out.println(Thread.currentThread().getName());
                endGate.countDown();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    class threadDemo implements Runnable{
        service ser = new service();
        CountDownLatch startGate;
        CountDownLatch endGate;
        public threadDemo(service ser,CountDownLatch endGate,CountDownLatch startGate){
            this.ser = ser;
            this.startGate = startGate;
            this.endGate = endGate;
        }
        public void run() {
            ser.sleeps(endGate,startGate);
        }
    }

    public class test4 {
        public static void main(String[] args){
            service ser = new service();
            threadDemo[] t = new threadDemo[150];
            CountDownLatch startGate = new CountDownLatch(1);
            CountDownLatch endGate = new CountDownLatch(150);

            for(int i=0;i<t.length;i++){
                t[i] = new threadDemo(ser,endGate,startGate);
                Thread t1 = new Thread(t[i]);
                t1.start();
            }
            long startTime = System.currentTimeMillis();
            startGate.countDown();
            try {
                endGate.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            long endTime = System.currentTimeMillis();
            System.out.println("用時: " + (endTime - startTime) + "ms");
        }
    }

協程:

import co.paralleluniverse.fibers.Fiber;
import co.paralleluniverse.fibers.SuspendExecution;
import co.paralleluniverse.strands.Strand;
import co.paralleluniverse.strands.SuspendableRunnable;
import java.util.concurrent.CountDownLatch;

/**
 * @Auther: muyu
 * @Date: 2018-10-11-16:52
 */

class service2 {
    public void doSleep(CountDownLatch startGate, CountDownLatch endGate) throws SuspendExecution {
        try {
            startGate.await();
            Strand.sleep(25);
            System.out.println(Thread.currentThread().getName());
            endGate.countDown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
class threadDemo2 implements SuspendableRunnable {
    service2 ser2 = new service2();
    CountDownLatch startGate;
    CountDownLatch endGate;
    public threadDemo2(service2 ser2,CountDownLatch startGate,CountDownLatch endGate){
        this.ser2 = ser2;
        this.startGate = startGate;
        this.endGate = endGate;
    }
    @Override
    public void run() throws SuspendExecution, InterruptedException {
        ser2.doSleep(startGate,endGate);
    }
}

public class xieChengTest {

    public static void main(String[] args) throws InterruptedException, SuspendExecution {
        service2 ser = new service2();
        threadDemo2[] fiber = new threadDemo2[150];
        CountDownLatch startGate = new CountDownLatch(1);
        CountDownLatch endGate = new CountDownLatch(150);
        for(int i=0;i<fiber.length;i++){
            fiber[i] = new threadDemo2(ser,startGate,endGate);
            Fiber f = new Fiber(fiber[i]);
            f.start();
        }
        long startTime = System.currentTimeMillis();
        startGate.countDown();
        try {
            endGate.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("用時: " + (endTime - startTime) + "ms");
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章