swoole協程


爲什麼下面的代碼不是順序執行的呢? 實際執行過程:
運行此段代碼, 系統啓動一個新進程
遇到 go(), 當前進程中生成一個協程
協程中遇到 IO阻塞 (這裏是 Co::sleep() 模擬出的 IO等待), 協程讓出控制, 進入協程調度隊列
進程繼續向下執行, 輸出 主作業
執行下一個協程, 輸出 作業02
之前的協程準備就緒, 繼續執行, 輸出 作業01
 

go(function () {

    //Co::sleep() 函數功能和 sleep() 差不多, 但是它模擬的是 IO等待
    Co::sleep(1);
    echo "作業01".PHP_EOL;
});

echo "主作業".PHP_EOL;

go(function () {
    echo "作業02".PHP_EOL;
});
協程快在哪? 減少IO阻塞導致的性能損失
大家可能聽到使用協程的最多的理由, 可能就是 協程快. 那看起來和平時寫得差不多的代碼, 爲什麼就要快一些呢? 一個常見的理由是, 可以創建很多個協程來執行任務, 所以快. 這種說法是對的, 不過還停留在表面.

首先, 一般的計算機任務分爲 2 種:

CPU密集型, 比如加減乘除等科學計算
IO 密集型, 比如網絡請求, 文件讀寫等
其次, 高性能相關的 2 個概念:

並行: 同一個時刻, 同一個 CPU 只能執行同一個任務, 要同時執行多個任務, 就需要有多個 CPU 纔行
併發: 由於 CPU 切換任務非常快, 快到人類可以感知的極限, 就會有很多任務 同時執行 的錯覺
瞭解了這些, 我們再來看協程, 協程適合的是 IO 密集型 應用, 因爲協程在 IO阻塞 時會自動調度, 減少IO阻塞導致的時間損失.

普通寫法, 會遇到 IO阻塞 導致的性能損失
單協程: 儘管 IO阻塞 引發了協程調度, 但當前只有一個協程, 調度之後還是執行當前協程
多協程: 真正發揮出了協程的優勢, 遇到 IO阻塞 時發生調度, IO就緒時恢復運行

sleep() 可以看做是 CPU密集型任務, 不會引起協程的調度
Co::sleep() 模擬的是 IO密集型任務, 會引發協程的調度
這也是爲什麼, 協程適合 IO密集型 的應用.

go 中的協程, 使用的 MPG 模型:

M 指的是 Machine, 一個M直接關聯了一個內核線程
P 指的是 processor, 代表了M所需的上下文環境, 也是處理用戶級代碼邏輯的處理器
G 指的是 Goroutine, 其實本質上也是一種輕量級的線程

而 swoole 中的協程調度使用 單進程模型, 所有協程都是在當前進程中進行調度, 單進程的好處也很明顯 -- 簡單 / 不用加鎖 / 性能也高
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章