自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Rust的并發(fā)模型 vs Go的并發(fā)模型:Stackless協(xié)程 vs Stackfull協(xié)程

開發(fā) 前端
雖然這些都在Go中得到了解決,在Go中,一切都是同步的,編譯器和運行時在調(diào)用程序員看不見的異步函數(shù)時自動插入等待點,但這是以性能損失(內(nèi)存和CPU)為代價的。

雖然Rust和Go都是從上一代編程語言的錯誤中吸取教訓(xùn)的現(xiàn)代編程語言,但它們以完全不同的方式管理并發(fā),這對性能和開發(fā)人員體驗有巨大的影響。

但首先,我們?yōu)槭裁葱枰l(fā)?

今天,大多數(shù)程序與需要一定時間才能返回響應(yīng)的資源進行交互:例如網(wǎng)絡(luò)或磁盤。如果我們在等待網(wǎng)絡(luò)響應(yīng)的同時完全阻塞程序的執(zhí)行,這將是對硬件的一種相當(dāng)?shù)托У氖褂茫?/p>

這就是為什么Go和Rust在等待I/O(輸入/輸出)時允許程序執(zhí)行其他任務(wù)的語言特性。

任務(wù)

任務(wù)是可以并發(fā)執(zhí)行的抽象計算單元:多個函數(shù)可以(由程序)同時處理,但它們不一定(由CPU)同時執(zhí)行(它的并行性需要多個線程)。

可以使用go關(guān)鍵字在Go中生成新任務(wù):

go doSomething()
go doAnotherThing()

在Rust中,需要使用spawn函數(shù):

tokio::spawn(async move {
     do_something().await
});

tokio::spawn(async move {
     do_another_thing().await
});

在這兩種情況下,任務(wù)都由語言的運行時同時處理。

運行時

運行時的目的是管理和調(diào)度不同的任務(wù),以便有效地使用硬件。

圖片圖片

Rust和Go的第一個不同之處。你不能改變Go運行時(除非你使用一個完全不同的編譯器,比如tinygo),它是內(nèi)置在語言中的,而在Rust中,語言沒有提供運行時,你必須自己配置。

函數(shù)在等待某些東西(例如網(wǎng)絡(luò))時將控制權(quán)交還給運行時。在Go中,這是由標(biāo)準(zhǔn)庫、語言和編譯器自動完成的,而在Rust中,它在到達(dá)await關(guān)鍵字時發(fā)生。

Stackfull協(xié)程

Stackfull協(xié)程又稱綠線程,或M:N線程(M個綠線程運行在N個內(nèi)核線程上)是Go采用的并發(fā)模型。

在這個模型中,運行時管理輕量級(綠色)線程,并將它們調(diào)度到可用的硬件線程上。與內(nèi)核線程一樣,每個任務(wù)都有自己的棧,如果需要,可以由運行時增加棧。

stackfull協(xié)程的第一個問題是,每個任務(wù)都有自己的棧,這意味著每個任務(wù)使用較少的內(nèi)存量。從Go 1.22開始,線程程序使用的最小內(nèi)存量是2 KiB,這意味著如果有10,000個并發(fā)任務(wù)在運行,程序?qū)⑹褂弥辽?0 MiB的內(nèi)存。

Stackfull協(xié)程的第二個問題是,運行時需要完全控制棧布局,這使得與其他語言(如C的FFI)的互操作性變得困難,因為運行時必須在能夠調(diào)用C代碼之前做一些準(zhǔn)備棧的工作。這就是為什么CGO被認(rèn)為是緩慢的(在現(xiàn)實中,CGO調(diào)用在30到75納秒內(nèi)完成,在我看來這是相當(dāng)快的)。

Stackless協(xié)程

另一方面,Rust采用了無棧協(xié)程方法,其中任務(wù)沒有自己的棧。在Rust中,F(xiàn)uture基本上是實現(xiàn)Future Trait的簡單結(jié)構(gòu),其中每個.await調(diào)用鏈被編譯成巨大的狀態(tài)機。

如果你正在用Python或c#開發(fā),你可能已經(jīng)知道async/await函數(shù)著色的巨大代價,其中同步函數(shù)不能調(diào)用async函數(shù),反之亦然。

這就導(dǎo)致了許多問題,比如導(dǎo)致了生態(tài)系統(tǒng)的碎片化,其中的庫是不可互操作的,很難在程序中使用libA,因為你使用的是async而不是這個庫,而且還導(dǎo)致了開發(fā)人員的許多錯誤,他們阻塞了運行時的事件循環(huán),降低了系統(tǒng)的性能。

這在Rust中也同樣存在,因為標(biāo)準(zhǔn)庫不提供與同步函數(shù)相同的異步函數(shù)(例如read讀取整個文件),并且因為不同的運行時甚至不能相互操作,如果你開始為tokio運行時編寫程序,你將很難將其移植到另一個運行時。

雖然這些都在Go中得到了解決,在Go中,一切都是同步的,編譯器和運行時在調(diào)用程序員看不見的異步函數(shù)時自動插入等待點,但這是以性能損失(內(nèi)存和CPU)為代價的。

雖然Rust方法可以最大限度地利用機器,但它帶來了一個碎片化的生態(tài)系統(tǒng),這給Rust的采用帶來了很大的麻煩。

責(zé)任編輯:武曉燕 來源: coding到燈火闌珊
相關(guān)推薦

2016-10-28 17:39:47

phpgolangcoroutine

2023-11-24 11:15:21

協(xié)程編程

2021-09-27 23:28:29

Go多協(xié)程并發(fā)

2023-10-12 09:46:00

并發(fā)模型線程

2021-09-16 09:59:13

PythonJavaScript代碼

2024-12-03 15:15:22

2023-11-17 11:36:59

協(xié)程纖程操作系統(tǒng)

2021-04-25 09:36:20

Go協(xié)程線程

2021-05-13 21:58:00

高并發(fā)應(yīng)用Asyncio

2020-11-30 08:25:41

程序員高并發(fā)協(xié)程

2018-12-04 14:00:41

協(xié)程編程模式PHP

2021-06-03 14:08:03

開發(fā)技能代碼

2021-06-04 14:28:07

協(xié)程線程Android開發(fā)

2024-02-05 09:06:25

Python協(xié)程Asyncio庫

2023-07-27 13:46:10

go開源項目

2024-08-27 09:46:39

Go協(xié)程效率

2025-02-08 09:13:40

2023-10-24 19:37:34

協(xié)程Java

2021-12-09 06:41:56

Python協(xié)程多并發(fā)

2022-10-28 10:45:22

Go協(xié)程GoFrame
點贊
收藏

51CTO技術(shù)棧公眾號