英文:
Golang. Zero Garbage propagation or efficient use of memory
问题
有时候我会遇到像“零垃圾”或高效使用内存等概念。例如,在知名包httprouter的“特性”部分,你可以看到以下内容:
**零垃圾:**匹配和调度过程不会产生任何垃圾字节。实际上,唯一进行的堆分配是为路径参数构建键值对切片。如果请求路径不包含参数,则不需要进行任何堆分配。
此外,与标准库的http.ServeMux相比,这个包显示出非常好的基准测试结果:
BenchmarkHttpServeMux 5000 706222 ns/op 96 B/op 6 allocs/op
BenchmarkHttpRouter 100000 15010 ns/op 0 B/op 0 allocs/op
据我了解,从表中可以看出第二个基准测试结果没有堆内存分配,并且每次重复操作的平均分配次数为零。
**问题:**我想了解内存管理的基本概念。垃圾收集器何时分配/释放内存?基准测试中的数字代表什么(表格的最后两列),人们如何知道何时进行堆分配?
我对内存管理完全是新手,所以很难理解“底层”发生了什么。我阅读过的文章有:
英文:
From time to time I face with the concepts like zero garbage or efficient use of memory etc. As an example in the section Features of well-known package httprouter you can see the following:
> Zero Garbage: The matching and dispatching process generates zero bytes of garbage. In fact, the only heap allocations that are made, is by building the slice of the key-value pairs for path parameters. If the request path contains no parameters, not a single heap allocation is necessary.
Also this package shows very good benchmark results compared to standard library's http.ServeMux:
BenchmarkHttpServeMux 5000 706222 ns/op 96 B/op 6 allocs/op
BenchmarkHttpRouter 100000 15010 ns/op 0 B/op 0 allocs/op
As far as I understand the second one has (from the table) no heap memory allocation and zero average number of allocations made per repetition.
The question: I want to learn a basic understanding of memory management. When garbage collector <del>allocates</del>/deallocates memory. What does the benchmark numbers means (the last two columns of the table) and how people know when heap is allocating?
I'm absolutely new in memory management, so it's really difficult to understand what's going on "under the hood". The articles I've read:
答案1
得分: 10
垃圾收集器不分配内存,只是释放内存。Go的垃圾收集器正在不断发展,详细信息请参阅设计文档https://docs.google.com/document/d/16Y4IsnNRCN43Mx0NZc5YXZLovrHvvLhK_h0KN8woTO4/preview?sle=true,并关注golang邮件列表上的讨论。
基准输出中的最后两列非常简单:总共分配了多少字节,以及在基准代码的一次迭代中进行了多少次分配(这些分配是由您的代码完成的,而不是由垃圾收集器完成的)。由于任何分配都可能创建垃圾,减少这些数字可能是一个设计目标。
什么时候会在堆上分配对象?取决于Go编译器的决策!编译器尝试在堆栈上分配,但有时必须使用堆,特别是当一个值从本地堆栈作用域中逃逸时。逃逸分析目前正在进行重构,因此很难确定哪个值将被分配到堆还是栈,特别是这在编译器版本之间会发生变化。
在你的基准测试显示出过多的垃圾收集开销之前,不要过于迷恋避免分配。
英文:
The garbage collector doesn't allocate memory :-), it just deallocates. Go's garbage collector is evolving, for the details have a look at the design document https://docs.google.com/document/d/16Y4IsnNRCN43Mx0NZc5YXZLovrHvvLhK_h0KN8woTO4/preview?sle=true and follow the discussion on the golang mailing lists.
The last two columns in the benchmark output are dead simple: How many bytes have been allocated in total and how many allocations have happened during one iteration of the benchmark code. (This allocation is done by your code, not by the garbage collector). As any allocation is a potential creation of garbage reducing these numbers might be a design goal.
When are things allocated on the heap? Whenever the Go compiler decides to! The compiler tries to allocate on the stack, but sometimes it must use the heap, especially if a value escapes from the local stack-bases scopes. This escape analysis is currently undergoing rework, so it is not easy to tell which value will be heap- or stack-allocated, especially as this is changing from compiler version to version.
I wouldn't be too obsessed with avoiding allocations until your benchmarking show too much GC overhead.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论