当我用make或new调用创建新的slice或struct时:
s := make([]int64, 10, 100) o := new(MyStruct)
Go通过内存分配系统调用分配多少内存?它是否预分配了内存,以便后续调用不会触发新的系统调用?
我问这个问题是因为我需要在代码中频繁分配内存。我不确定是否需要自己实现一个内存分配器,还是可以依靠Go来完成肮脏的工作。如果Go确实预分配了内存,我可以自定义要分配的块大小吗?
我在Go中编写了一些实验代码,并在strace下运行该代码,但我不了解Go对mmap系统调用的作用:
mmap(0xc000000000, 65536, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xc000000000 munmap(0xc000000000, 65536) = 0 mmap(NULL, 262144, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efdd1017000 mmap(0xc208000000, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xc208000000 mmap(0xc207ff0000, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xc207ff0000 mmap(0xc000000000, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xc000000000 mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efdd1007000 mmap(NULL, 1439992, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7efdd0ea7000
您可能在这里遭受“过早优化”综合症。语言规范 没有 说明将如何精确分配分配的内存make()。
make()
例如,一个合格的Go实现可能会对功能进行彻底的分析,make([]foo, ...)并证明:
make([]foo, ...)
append()
在这种情况下,可以在堆栈上直接分配片的后备存储。
当然,我正在汇总,但再次说明,此语言的语义未在语言规范中声明。目前,有两种成熟的Go实施(一种起源于Google,被称为gc和gccgo),还有更多的实现(llvmgo似乎有很多机会实现),而且它们都有其独特之处。
gc
gccgo
llvmgo
因此,请考虑pprof总体上阅读和Go分析,并进行个人资料示例(但实际)代码。
pprof
在邮件列表中搜索单词“ profile”,“ profiling”,“ heap AND profile”,“ CPU AND profile”和“ pprof”将为您提供很多见解。
也考虑这个和这个。