2 回答
TA贡献1804条经验 获得超2个赞
这本书正在谈论“磁盘结构”。在此上下文中,页面仅表示数据块。磁盘访问在扇区或集群中工作,因此应针对局部性优化数据,以便尽可能地适应这些块。数据库文件设计的挑战是将数据的时间局部性转换为空间局部性。
但这个概念也适用于RAM。在用户空间虚拟内存中的页面级别工作仅意味着了解底层内存体系结构并对其进行优化。
在 x86 上,用户空间虚拟内存以 4 KB* 的页为单位进行组织。
这意味着,在处理大量数据时,使用内存区域是值得的,内存区域是 4 KB 的倍数,与 4 KB 对齐。
在C中,有很多方法可以实现这一目标,例如.aligned_alloc
但是Go走得更远 - 它已经至少在页面大小(在Mac,BSD,Linux和Windows上)对齐了大型数组。
func main() {
buf := make([]byte, 1024*1024)
fmt.Printf("%p\n", unsafe.Pointer(&buf[0]))
}
将打印如下内容:
0xc000180000
如果您遇到不这样做的实现,您始终可以“手动”对齐切片,方法是分配PageSize-1额外的字节,然后跳过开头的字节,这些字节不是从PageSize的倍数开始的,使用对齐公式:byte
偏移量 = (对齐 - 基数) & (对齐 - 1)
func main() {
buf := make([]byte, 1024*1024 + 4096 - 1)
base := unsafe.Pointer(&buf[0])
offset := (4096 - uintptr(base)) & (4096 - 1)
aligned := buf[offset:]
fmt.Printf("base : %p\n", unsafe.Pointer(&buf[0]))
fmt.Printf("aligned: %p\n", unsafe.Pointer(&aligned[0]))
}
(想不出上面会打印不同值的平台)
* 某些平台支持 2MB 和 1GB 页面的大页面。Go 会在可用时自动使用它们。
TA贡献1821条经验 获得超4个赞
我可能错过了一些东西,但是使用物理内存(与虚拟内存相反)不是语言功能,而是操作系统
的功能。
每个操作系统都提供了使用实际地址空间的方法,这些服务需要提升的权限,并作为驱动程序/内核模块提供,并使用此访问进行内存映射IO或预分配物理内存块(在MMI将其用作分页内存之前)。
我想在系统负载(通过驱动程序)上预先分配内存块并使用它是您希望做的。
如果您打算在“物理内存”上访问“虚拟内存”,我会劝阻您并说这是一个非常微妙和脆弱的机制,除非您发现这样做的巨大优势,否则我看不到任何理由走这条路。
- 2 回答
- 0 关注
- 79 浏览
添加回答
举报