似乎有一种观点认为,在64位体系 struct 上不需要使用"拆分堆栈"运行时模型.我说似乎是,因为我没有看到任何人真的这么说,只是绕着它跳舞:

典型多线程程序的内存使用量可以减少 值得注意的是,因 for each 线程不需要最坏情况下的堆栈 尺码.可以运行数百万个线程(或者完整的NPTL 线程或协同 routine )在32位地址空间中. --Ian Lance Taylor

.这意味着64位地址空间已经可以处理它.

而且...

...拆分堆栈的恒定开销和狭隘的用例 (在32位体系 struct 上产生大量I/O受限任务) 是不可接受的... --bstrie

两个问题:这是他们在说的吗?其次,如果是这样,为什么在64位体系 struct 上不需要它们呢?

推荐答案

是的,他们就是这么说的.

拆分堆栈(目前)在64位体系 struct 上是不必要的,因为64位虚拟地址空间非常大,如果需要,可以包含数百万个堆栈地址范围,每个堆栈地址范围与整个32位地址空间一样大.

在目前使用的Flat memory model中,虚拟地址到物理存储单元的转换是在hardware MMU的支持下完成的.在amd64上,将64位虚拟地址空间的大块保留给您正在创建的每个新堆栈,同时只将第一页(4kB)映射到实际RAM会更好(总体上更快).这样,当OS重新配置MMU以将每页虚拟地址映射到实际的空闲RAM页时,堆栈将能够根据需要在连续的虚拟地址(意味着每个function prologue中的代码更少,这是一个大的优化)上根据需要增长和缩小,只要堆栈增长或缩小高于/低于某些可配置的阈值就会增长或缩小.在这种情况下,堆栈将能够在连续的虚拟地址(意味着每个function prologue中的代码更少,这是一个很大的优化)上根据需要增长和缩小.

通过巧妙地 Select 阈值(例如,参见dynamic arrays理论),您可以在平均堆栈操作上实现O(1)复杂度,同时保留数百万个堆栈的优点,这些堆栈可以根据您的需要增长,并且只消耗它们使用的内存.

PS:目前的GO实现远远落后于这些:-)

Go相关问答推荐

Golang使用Run()执行的命令没有返回

通过代理从golang连接到ftp

当我有外键时,如何使用 GORM 创建数据库的新条目

从带有嵌套括号的字符串中提取值

go-chi: 接受带有反斜杠的 url 路径参数

Go 中的sync.Cond 与 Wait 方法

为什么我只收到部分错误而不是我启动的 goroutines 的所有错误?

如何将 DirName 和 serial 添加到 X509v3 Authority Key Identifier

接受通道和切片的通用函数

如何将一片 map 转换为一片具有不同属性的 struct

将 Golang Gin 与 AWS Lambda 和无服务器与代理路径一起使用

httprouterhttp.HandlerFunc() 是如何工作的?

如何使路径/不匹配 Golang net/http 中所有其他不匹配的路径

如何从 docker-compose 命令运行 2 个不同的命令:

try 执行`go test ./... -v`时,Golang中有没有办法设置标志

如何在 Gorm 中获得特定日期的最大值?

并发 map map导致的 Golang 数据竞争

如何获取文件的 ctime、atime、mtime 并更改它们

Go 系统调用 vs. C 系统调用

相当于go中python的ord()、chr()?