首页>国内 > 正文

Go 要违背初心吗?新提案:手动管理内存

2022-11-15 10:04:50来源:脑子进煎鱼了

背景

由于手动管理内存普遍会给程序员带来一定的心智负担,提高一门编程语言的入门门槛(还记得大学写 OC 时经常有同学写着写崩了...)。


(资料图)

对应到 Go 语言上,他是一门带垃圾回收的编程语言。也就是说不需要程序员手动的去管理、释放程序的内存。

无需手动管理也是 Go 核心开发团队一直引以为傲的特性之一。

最近有人发起了一个新提案《proposal: arena: new package providing memory arenas》,引起了非常广泛的讨论。

如下图:

接下来我们将面向该提案进行学习和了解。

新提案

本提案所提到的 Arena,指的是一种从一个连续的内存区域分配一组内存对象的方式。优点是 arena 中的对象分配通常比一般的内存分配更有效率,所分配的对象可以一次性释放,以此达到内存管理或垃圾收集的开销最小。

其建议在 Go 的标准库中支持 arena。标准 API 如下:

package arenatype Arena struct { // contains filtered or unexported fields}// New allocates a new arena.func New() *Arena// Free frees the arena (and all objects allocated from the arena) so that// memory backing the arena can be reused fairly quickly without garbage// collection overhead.  Applications must not call any method on this// arena after it has been freed.func (a *Arena) Free()// New allocates an object from arena a.  If the concrete type of objPtr is// a pointer to a pointer to type T (**T), New allocates an object of type// T and stores a pointer to the object in *objPtr.  The object must not// be accessed after arena a is freed.func (a *Arena) New(objPtr interface{})// NewSlice allocates a slice from arena a.  If the concrete type of slicePtr// is *[]T, NewSlice creates a slice of element type T with the specified// capacity whose backing store is from the arena a and stores it in// *slicePtr. The length of the slice is set to the capacity.  The slice must// not be accessed after arena a is freed.func (a *Arena) NewSlice(slicePtr interface{}, cap int)

这一实践已经在 Google 得到了应用,且在一些大型应用程序中节省了高达 15% 的CPU和内存使用,这主要是由于减少了垃圾收集的CPU时间和堆内存使用所带来的效果。

arena 若成为标准库的使用的例子:

import ( “arena” …)type T struct { val int}func main() { a := arena.New() var ptrT *T a.New(&ptrT) ptrT.val = 1 var sliceT []T a.NewSlice(&sliceT, 100) sliceT[99].val = 4 a.Free()}

手动调用arena.New​方法分配 arena 内存,再调用Free方法进行释放。

当然,一般提案中所提到的 arena 并不会在一门带垃圾回收的编程语言中实现。因为会操作到内存就有可能会不安全,不符合带垃圾回收的语言定义。

该库底层采取了动态检查来确保 arena 释放内存的操作是安全的。若出现异常情况,就会终止释放。

争论

围绕这这个新的提案,评论区的网友们争议的非常多。有的会疑惑,为什么一定要放在标准库,放第三方库不行吗?

实际上在第三方库中很难安全地做到这一点,因为一个在 arena 库中分配的变量,他包含指向外部的内存指针,要确保性能下让 GC 知道他,否则可能会导致错误的释放。

当然,也有人提出,这 Go 就变成像 C++ 一样,忘记 free、重复 free、提前 free,与 Go 原先标榜的简洁相差甚远。

总结

现阶段该提案还在积极探讨的阶段,原型代码也已经提交《runtime: prototype CL showing possible implementation of arenas》有兴趣的小伙伴可以抽时间看看。

这个提案争议较大,你很难说他是一个库,还是一个语言的根本性变更。你一旦在原生标准库支持了,其他关联的也必然会支持其 API,自然而然就植入进去了,与 “unsafe” 标准库定位一致,都是不安全的因素。

大家怎么看?

关键词: 编程语言 垃圾回收 垃圾收集 非常广泛 自然而然

相关新闻

Copyright 2015-2020   三好网  版权所有 联系邮箱:435 22 640@qq.com  备案号: 京ICP备2022022245号-21