為什麼協程切換的代價比執行緒切換低

2021-09-28 17:35:15 字數 964 閱讀 7162

先說結論:協程切換比執行緒切換快主要有兩點:

(1)協程切換完全在使用者空間進行,執行緒切換涉及特權模式切換,需要在核心空間完成

(2)協程切換相比執行緒切換做的事情更少

協程切換只涉及基本的cpu上下文切換,所謂的 cpu 上下文,就是一堆暫存器,裡面儲存了 cpu執行任務所需要的資訊:從**開始執行(%rip:指令指標暫存器,標識 cpu 執行的下一條指令),棧頂的位置(%rsp: 是堆疊指標暫存器,通常會指向棧頂位置),當前棧幀在哪(%rbp 是棧幀指標,用於標識當前棧幀的起始位置)以及其它的cpu的中間狀態或者結果(%rbx,%r12,%r13,%14,%15 等等)。協程切換非常簡單,就是把當前協程的 cpu 暫存器狀態儲存起來,然後將需要切換進來的協程的 cpu 暫存器狀態載入的 cpu 暫存器上就 ok 了。而且完全在使用者態進行,一般來說一次協程上下文切換最多就是幾十ns 這個量級。下面給出 libco 的協程切換的彙編**,也就是二十來條彙編指令,完成當前協程 cpu 暫存器的儲存,並恢復排程進來的 cpu 暫存器狀態,類似的也可以參考 boost context 裡面的切換彙編**,大同小異。

系統核心排程的物件是執行緒,因為執行緒是排程的基本單元(程序是資源擁有的基本單元,程序的切換需要做的事情更多,這裡佔時不討論程序切換),而執行緒的排程只有擁有最高許可權的核心空間才可以完成,所以執行緒的切換涉及到使用者空間和核心空間的切換,也就是特權模式切換,然後需要作業系統排程模組完成執行緒排程(taskstruct),而且除了和協程相同基本的 cpu 上下文,還有執行緒私有的棧和暫存器等,說白了就是上下文比協程多一些,其實簡單比較下 task_strcut 和 任何乙個協程庫的 coroutine 的 struct 結構體大小就能明顯區分出來。而且特權模式切換的開銷確實不小,隨便搜一組測試資料 [3],隨便算算都比協程切換開銷大很多。

協程的多執行緒切換

我們知道,在乙個基於協程的應用程式中,可能會產生數以千記的協程,所有這些協程,會有乙個的排程器來統一排程。另外我們知道,高效能的程式首要注意的就是避免程式阻塞。那麼,在以協程為最小執行單位的程式中,同樣也需要確保這一點,即每乙個協程都不能發生阻塞。因為只要某乙個協程發生了阻塞,那麼整個排程器就阻塞住...

協程的多執行緒切換

我們知道,在乙個基於協程的應用程式中,可能會產生數以千記的協程,所有這些協程,會有乙個的排程器來統一排程。另外我們知道,高效能的程式首要注意的就是避免程式阻塞。那麼,在以協程為最小執行單位的程式中,同樣也需要確保這一點,即每乙個協程都不能發生阻塞。因為只要某乙個協程發生了阻塞,那麼整個排程器就阻塞住...

Go程序 執行緒 協程 單元 空間資源 切換 共享

程序process 執行緒 thread 協程goroutine 作業系統分為操作與資源兩部分,操作就是方法,資源就是硬碟資源,合稱為作業系統。因為是乙個系統,任務很多很繁雜,所以根據軟體不同進行分解,乙個軟體就是一小塊,就是程序。比喻 程序就是應用程式的啟動例項,乙個軟體乙個程序,例如我們執行乙個...