stackless和 stackful对应的是协程中栈的内存, stackless表示栈内存位置不固定,而 stackful则需要分配一个固定的栈内存。
在 继续执行( Continuation/ MoveNext())时, stackless需要编译器生成代码,如闭包,来自定义 继续执行逻辑;而 stackful则直接从原栈的位置 继续执行。
性能方面, stackful的中断返回需要依赖控制 CPU的跳转位置来实现,属于骚操作,会略微影响 CPU的分支预测,从而影响性能(但影响不算大),这方面 stackless无影响。
内存方面, stackful需要分配一个固定大小的栈内存(如 4kb),而 stackless只需创建带一个状态号变量的状态机, stackful占用的内存更大。
骚操作方面, stackful可以轻松实现完全一致的递归/异常处理等,没有任何影响,但 stackless需要编译器作者高超的技艺才能实现(如 C#的作者),注意最初的 C# 5.0在 try-catch块中是不能写 await的。
和已有组件结合/框架依赖方面, stackless需要定义一个状态机类型,如 Task<T>/ IEnumerable<T>/ IAsyncEnumerable<T>等,而 stackful不需要,因此这方面 stackless较麻烦。
Go属于 stackful,因此每个 goroutine需要分配一个固定大小的内存。
C#属于 stackless,它会创建一个闭包和状态机,需要编译器生成代码来指定 继续执行逻辑。
总结如下:
stacklessstackful内存位置不固定固定继续执行编译器定义CPU跳转性能/速度快快,但影响分支预测内存占用低需要固定大小的栈内存编译器难度难适中组件依赖不方便方便嵌套不支持支持举例C#/ jsGo/ C++Boost
stackless和 stackful对应的是协程中栈的内存, stackless表示栈内存位置不固定,而 stackful则需要分配一个固定的栈内存。
在 继续执行( Continuation/ MoveNext())时, stackless需要编译器生成代码,如闭包,来自定义 继续执行逻辑;而 stackful则直接从原栈的位置 继续执行。
性能方面, stackful的中断返回需要依赖控制 CPU的跳转位置来实现,属于骚操作,会略微影响 CPU的分支预测,从而影响性能(但影响不算大),这方面 stackless无影响。
内存方面, stackful需要分配一个固定大小的栈内存(如 4kb),而 stackless只需创建带一个状态号变量的状态机, stackful占用的内存更大。
骚操作方面, stackful可以轻松实现完全一致的递归/异常处理等,没有任何影响,但 stackless需要编译器作者高超的技艺才能实现(如 C#的作者),注意最初的 C# 5.0在 try-catch块中是不能写 await的。
和已有组件结合/框架依赖方面, stackless需要定义一个状态机类型,如 Task<T>/ IEnumerable<T>/ IAsyncEnumerable<T>等,而 stackful不需要,因此这方面 stackless较麻烦。
Go属于 stackful,因此每个 goroutine需要分配一个固定大小的内存。
C#属于 stackless,它会创建一个闭包和状态机,需要编译器生成代码来指定 继续执行逻辑。
总结如下:
stacklessstackful内存位置不固定固定继续执行编译器定义CPU跳转性能/速度快快,但影响分支预测内存占用低需要固定大小的栈内存编译器难度难适中组件依赖不方便方便嵌套不支持支持举例C#/ jsGo/ C++Boost