Rust的并发模型 vs Go的并发模型:Stackless协程 vs Stackfull协程

开发 前端
虽然这些都在Go中得到了解决,在Go中,一切都是同步的,编译器和运行时在调用程序员看不见的异步函数时自动插入等待点,但这是以性能损失(内存和CPU)为代价的。

虽然Rust和Go都是从上一代编程语言的错误中吸取教训的现代编程语言,但它们以完全不同的方式管理并发,这对性能和开发人员体验有巨大的影响。

但首先,我们为什么需要并发?

今天,大多数程序与需要一定时间才能返回响应的资源进行交互:例如网络或磁盘。如果我们在等待网络响应的同时完全阻塞程序的执行,这将是对硬件的一种相当低效的使用!

这就是为什么Go和Rust在等待I/O(输入/输出)时允许程序执行其他任务的语言特性。

任务

任务是可以并发执行的抽象计算单元:多个函数可以(由程序)同时处理,但它们不一定(由CPU)同时执行(它的并行性需要多个线程)。

可以使用go关键字在Go中生成新任务:

go doSomething()
go doAnotherThing()

在Rust中,需要使用spawn函数:

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

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

在这两种情况下,任务都由语言的运行时同时处理。

运行时

运行时的目的是管理和调度不同的任务,以便有效地使用硬件。

图片图片

Rust和Go的第一个不同之处。你不能改变Go运行时(除非你使用一个完全不同的编译器,比如tinygo),它是内置在语言中的,而在Rust中,语言没有提供运行时,你必须自己配置。

函数在等待某些东西(例如网络)时将控制权交还给运行时。在Go中,这是由标准库、语言和编译器自动完成的,而在Rust中,它在到达await关键字时发生。

Stackfull协程

Stackfull协程又称绿线程,或M:N线程(M个绿线程运行在N个内核线程上)是Go采用的并发模型。

在这个模型中,运行时管理轻量级(绿色)线程,并将它们调度到可用的硬件线程上。与内核线程一样,每个任务都有自己的栈,如果需要,可以由运行时增加栈。

stackfull协程的第一个问题是,每个任务都有自己的栈,这意味着每个任务使用较少的内存量。从Go 1.22开始,线程程序使用的最小内存量是2 KiB,这意味着如果有10,000个并发任务在运行,程序将使用至少20 MiB的内存。

Stackfull协程的第二个问题是,运行时需要完全控制栈布局,这使得与其他语言(如C的FFI)的互操作性变得困难,因为运行时必须在能够调用C代码之前做一些准备栈的工作。这就是为什么CGO被认为是缓慢的(在现实中,CGO调用在30到75纳秒内完成,在我看来这是相当快的)。

Stackless协程

另一方面,Rust采用了无栈协程方法,其中任务没有自己的栈。在Rust中,Future基本上是实现Future Trait的简单结构,其中每个.await调用链被编译成巨大的状态机。

如果你正在用Python或c#开发,你可能已经知道async/await函数着色的巨大代价,其中同步函数不能调用async函数,反之亦然。

这就导致了许多问题,比如导致了生态系统的碎片化,其中的库是不可互操作的,很难在程序中使用libA,因为你使用的是async而不是这个库,而且还导致了开发人员的许多错误,他们阻塞了运行时的事件循环,降低了系统的性能。

这在Rust中也同样存在,因为标准库不提供与同步函数相同的异步函数(例如read读取整个文件),并且因为不同的运行时甚至不能相互操作,如果你开始为tokio运行时编写程序,你将很难将其移植到另一个运行时。

虽然这些都在Go中得到了解决,在Go中,一切都是同步的,编译器和运行时在调用程序员看不见的异步函数时自动插入等待点,但这是以性能损失(内存和CPU)为代价的。

虽然Rust方法可以最大限度地利用机器,但它带来了一个碎片化的生态系统,这给Rust的采用带来了很大的麻烦。

责任编辑:武晓燕 来源: coding到灯火阑珊
相关推荐

2016-10-28 17:39:47

phpgolangcoroutine

2023-11-24 11:15:21

协程编程

2021-09-27 23:28:29

Go多协程并发

2023-10-12 09:46:00

并发模型线程

2021-09-16 09:59:13

PythonJavaScript代码

2024-12-03 15:15:22

2023-11-17 11:36:59

协程纤程操作系统

2021-04-25 09:36:20

Go协程线程

2021-05-13 21:58:00

高并发应用Asyncio

2020-11-30 08:25:41

程序员高并发协程

2018-12-04 14:00:41

协程编程模式PHP

2021-06-04 14:28:07

协程线程Android开发

2021-06-03 14:08:03

开发技能代码

2024-02-05 09:06:25

Python协程Asyncio库

2023-07-27 13:46:10

go开源项目

2024-08-27 09:46:39

Go协程效率

2023-10-24 19:37:34

协程Java

2021-12-09 06:41:56

Python协程多并发

2017-09-22 16:08:16

Python协程编程

2022-10-28 10:45:22

Go协程GoFrame
点赞
收藏

51CTO技术栈公众号