Go arena 民间库来了,可以手动管理内存!

今天给大家分享了 Go 官方 arena 的最新进展和情况,主体上还是由于严重 API 原因(担忧像 context 一样造成传染性)没有突破性进展。虽然有人提出可以放到 unsafe 库中,也获得了许多人表情点赞。但仍然没能打动 Go 核心团队的同学。

今天给大家分享了 Go 官方 arena 的最新进展和情况,主体上还是由于严重 API 原因(担忧像 context 一样造成传染性)没有突破性进展。虽然有人提出可以放到 unsafe 库中,也获得了许多人表情点赞。但仍然没能打动 Go 核心团队的同学。

大家好,我是煎鱼。

上年我们有讨论过关于 Go arena 手动管理内存的相关提案。一开始还高歌猛进,但没想到后面由于严重的 API 问题(想把 arena 应用到其他的标准库中,但会引入大问题):

图片图片

Go 核心团队中途咕咕咕到现在,没有新的推动和突破性进展,实属尴尬。

图片图片

最近有社区的大佬有了新的动作,来自 Grafana 的 @Miguel Ángel Ortuño 开源了一个新的第三方库ortuman/nuke[1],用于完成 arena 手动管理内存的诉求。

今天我们基于官方资料此进行使用分享和介绍,也好未雨绸缪一下。

温习前置知识

Arena 指的是一种从一个连续的内存区域分配一组内存对象的方式。当然了,它的重点是要手动管理内存,实现一些编程上的内存管理目标。

优点比一般的内存分配更有效率,也可以一次性释放。缺点上需要程序员在编程时手动管理,有可能会泄漏和错释放,增大了心智负担。

简单来讲就是,Arena 可以手动管理内存,可以做很多事,有利有弊。也 “容易” 崩。

快速介绍

安装

安装命令如下:

go get -u github.com/ortuman/nuke

需要注意这个库要求 go >= 1.21.7,在实际下载前建议先进行升级。

使用案例

常规使用

基本使用该 arean 库的用法,代码如下:

import (
 "github.com/ortuman/nuke"
)

type Foo struct{ A int }

func main() {
 arena := nuke.NewMonotonicArena(256*1024, 80)

 fooRef := nuke.New[Foo](arena "Foo")
 fooSlice := nuke.MakeSlice[Foo](arena, 0, 10 "Foo")

 for i := 0; i < 20; i++ {
  fooSlice = nuke.SliceAppend(arena, fooSlice, Foo{A: i})
 }
 // 做一些煎鱼的业务逻辑...
    
 arena.Reset(true)
 ...
}
  • 初始化一个新的 arean 内存区域,缓冲区大小为 256KB,最大内存上限为 20MB。
  • 声明和分配一个 Foo 类型的新对象和容量为 10 个元素的 Foo 切片。
  • 业务逻辑完成后,重置所申请的 arean 内存区域(释放)。

以上是最常用的方式,相当于在某一块代码片段中进行初始化和处理。

基于 context 场景

如果我们需要在 HTTP 请求这类整个生命周期中去使用。

可以借助 context,使用如下方式:

func httpHandler(w http.ResponseWriter, r *http.Request) {
    arena := nuke.NewMonotonicArena(64*1024, 10)
    defer arena.Reset(true)

    ctx := nuke.InjectContextArena(r.Context(), arena)
    processRequest(ctx)
    // 给煎鱼静悄悄干点什么...
}

func processRequest(ctx context.Context) {
    arena := nuke.ExtractContextArena(ctx)

    // ...
}

func main() {
    http.HandleFunc("/", httpHandler)    fmt.Println("Server is listening on port 8080...")
    http.ListenAndServe(":8080", nil)
}

在请求端 http context 中注入 arena,再在实际处理的地方通过 context 获取 arena,以此达到穿越整体生命周期的方式。

基于并发场景

默认场景下,nuke.NewMonotonicArena初始化出来的 arena,有一个隐性的坑,他不是并发安全的!

大胆猜测,这是基于性能的考虑,所以没有做到一起。毕竟锁会很吃资源。而在 Go 里要去做手动内存管理的场景,多少又对性能有一定的诉求。

在有并发诉求的场景下,可以使用NewConcurrentArena函数:

import (
 "github.com/ortuman/nuke"
)

func main() {
 arena := nuke.NewConcurrentArena(
            nuke.NewMonotonicArena(256*1024, 20),
        )
 defer arena.Reset(true)
 // 和煎鱼煎个鱼看看...
}

除了换了个初始化方法,其他用法与常规用法差不多。

也看了下官方的 Benchmarks,确实是基于性能考虑的区分并发与非并发的业务场景。QPS 越大,性能差距越大:

BenchmarkMonotonicArenaNewObject/100-8                    124495      15469 ns/op        0 B/op        0 allocs/op
BenchmarkMonotonicArenaNewObject/1000-8                    76744      19602 ns/op        0 B/op        0 allocs/op
BenchmarkMonotonicArenaNewObject/10000-8                   24104      50845 ns/op        0 B/op        0 allocs/op
BenchmarkMonotonicArenaNewObject/100000-8                   3282     366044 ns/op        0 B/op        0 allocs/op
BenchmarkConcurrentMonotonicArenaNewObject/100-8           90392      16679 ns/op        0 B/op        0 allocs/op
BenchmarkConcurrentMonotonicArenaNewObject/1000-8          43753      29823 ns/op        0 B/op        0 allocs/op
BenchmarkConcurrentMonotonicArenaNewObject/10000-8          8037     149923 ns/op        0 B/op        0 allocs/op
BenchmarkConcurrentMonotonicArenaNewObject/100000-8          879    1364377 ns/op

总结

今天给大家分享了 Go 官方 arena 的最新进展和情况,主体上还是由于严重 API 原因(担忧像 context 一样造成传染性)没有突破性进展。虽然有人提出可以放到 unsafe 库中,也获得了许多人表情点赞。但仍然没能打动 Go 核心团队的同学。

基于此,我们介绍了民间大佬的 arena 开源库 ortuman/nuke。基本功能和使用都能够满足需求。后续有此类业务需求时,可以随时拿起来就用!

参考资料

[1]ortuman/nuke:https://github.com/ortuman/nuke

©本文为清一色官方代发,观点仅代表作者本人,与清一色无关。清一色对文中陈述、观点判断保持中立,不对所包含内容的准确性、可靠性或完整性提供任何明示或暗示的保证。本文不作为投资理财建议,请读者仅作参考,并请自行承担全部责任。文中部分文字/图片/视频/音频等来源于网络,如侵犯到著作权人的权利,请与我们联系(微信/QQ:1074760229)。转载请注明出处:清一色财经

(0)
打赏 微信扫码打赏 微信扫码打赏 支付宝扫码打赏 支付宝扫码打赏
清一色的头像清一色管理团队
上一篇 2024年3月13日 00:06
下一篇 2024年3月13日 00:06

相关推荐

发表评论

登录后才能评论

联系我们

在线咨询:1643011589-QQbutton

手机:13798586780

QQ/微信:1074760229

QQ群:551893940

工作时间:工作日9:00-18:00,节假日休息

关注微信