Go在make或new调用中如何分配内存?

huangapple go评论88阅读模式
英文:

How does Go allocate memory in make or new calls?

问题

当我使用make或new调用创建一个新的切片或结构体时:

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
英文:

When I create a new slice or struct with a make or new call:

s := make([]int64, 10, 100)
o := new(MyStruct)

How much memory does Go allocate with a memory allocation system call? Does it pre-allocate memory, so that subsequent calls don't trigger new system calls?

I am asking this because I need to allocate memory frequently in my code. I am not sure if I need to implement a memory allocater myself, or if I can depend on Go to do the dirty work. And if Go does pre-allocate memory, can I customize the chunk size for allocation?

I write some experiment code in Go, and run the code under strace, but I do not understand what Go does with the mmap system calls:

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

答案1

得分: 2

你可能正在遭受“过早优化”综合症的困扰。语言规范对于make()分配的内存如何分配没有明确说明。

例如,Go的一个符合规范的实现可能会对执行make([]foo, ...)的函数进行彻底分析,并证明:

  1. 返回的切片值不会逃逸出函数的作用域。
  2. 不会对该切片值调用append()
  3. 该切片值不会传递给任何被调用的函数。

在这种情况下,切片的底层数组可能会直接分配在栈上。

当然,我有点夸张,但是再次强调,这些语义在语言规范中没有声明。目前有两个成熟的Go实现(一个源自Google,称为gc,另一个是gccgo),还有更多的实现即将到来(llvmgo似乎有很大的机会)。它们都有各自的特点。

因此,请考虑阅读关于pprof和Go性能分析的相关内容,并对实际代码进行分析。

邮件列表中搜索关键词“profile”、“profiling”、“heap AND profile”、“CPU AND profile”和“pprof”将为您提供很多见解。

还可以参考这篇文章这篇文章

英文:

You might suffer from the "premature optimization" syndrome here. The language spec says nothing about how exactly the memory allocated by make() will be allocated.

For instance, a conforming implementation of Go might perform thorough analyzis of the function which does make([]foo, ...) and prove that:

  1. The slice value returned does not escape the function's scope.
  2. append() is not called on this slice value.
  3. The slice value it not passed to any called function.

In this case, the slice's backing store might be allocated right on the stack.

Sure I'm exaggregating but again, the semantics of this are not declared in the language specification. And there are currently two mature Go implementations (that one originated from Google, dubbed gc, and gccgo) with more to come (llvmgo seems like having a good chances to live up), and they all have their peculiarities.

So please consider reading up on pprof and Go profiling in general, and do profile sample (but real) code.

Searching the mailing list for the words "profile", "profiling", "heap AND profile", "CPU AND profile" and "pprof" will provide lots of insight on it to you.

Consider also this and this.

huangapple
  • 本文由 发表于 2015年7月22日 10:51:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/31553048.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定