Go如何在make或new calls中分配内存? [英] How does Go allocate memory in make or new calls?

查看:174
本文介绍了Go如何在make或new calls中分配内存?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

  s:= make([] int64)使用make或new调用创建新的片或结构,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, (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()分配的内存究竟是如何分配的。



例如,Go的符合实现可以执行 make([] foo,...)的函数的彻底分析,并证明: p>


  1. 返回的切片值不会转义该函数的作用域。
  2. append( )不会在此切片值上调用。
  3. 切片值不会传递给任何调用的函数。

在这种情况下,切片的后备存储可能会被分配到堆栈中。



当然,我会重新集聚,它的语义没有在语言规范中声明。目前有两个成熟的Go实现(一个来自Google,被称为 gc gccgo ),其中更多( llvmgo 好像有很好的机会),并且它们都有它们的特点。



请考虑阅读 pprof 以及Go概要分析,并进行概要样本(但是真实的)代码。



邮件列表中搜索个人资料,个人资料, 堆和配置文件,CPU和配置文件和pprof将提供给你很多洞察力。



还可以考虑 this and 这个


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

解决方案

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.

这篇关于Go如何在make或new calls中分配内存?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆