写点什么

Golang 1.23: 新的 unique 包

作者:huizhou92
  • 2024-06-11
    北京
  • 本文字数:2375 字

    阅读完需:约 8 分钟

Golang 1.23: 新的 unique 包

上周,Go 1.23 进入冻结期,这意味着不会添加任何新功能,并且任何已添加的功能不太可能被删除。这是一个预览即将发生的变化的好机会。


这篇文章,我们来介绍引入的新包 unique


This article is first published in the medium MPP plan. If you are a medium user, please follow me in medium. Thank you very much.


根据wikipedia的描述,interning 是按需重复使用具有同等值对象的技术,减少创建新对象的动作。这种创建模式经常用于不同编程语言中的数和字符串,可以避免不必要的对象重复分配的开销。


unique 参考了go4.org/intern ,将它移动到了 官方库,并且做了相应的修改。 issue #62483


就像官方描述的一样 unique 这个包提供了一种轻量化(unique 仅仅八个字节)的比较两个变量是否相等的实现。比如下面这段代码

type testStruct2 struct {	c1 string	c2 string	c3 testStruct3}type testStruct3 struct {	c31 string	c32 string}type testStructData struct {	a int	b string	c testStruct2}
func BenchmarkMake1(b *testing.B) { c1 := testStructData{ a: 12, b: "eee", c: testStruct2{ c1: "aaa", c2: "bbb", c3: testStruct3{ c31: "ccc", c32: "ddd", }, }, } for i := 0; i < b.N; i++ { compareTestStructData(c1, c1) }}func BenchmarkMake2(b *testing.B) { c1 := testStructData{ a: 12, b: "eee", c: testStruct2{ c1: "aaa", c2: "bbb", c3: testStruct3{ c31: "ccc", c32: "ddd", }, }, } u1 := Make(c1) u2 := Make(c1) for i := 0; i < b.N; i++ { compareTestStructData1(u1, u2) }
}
func compareTestStructData1(u1 Handle[testStructData], u2 Handle[testStructData]) bool { return u1 == u2}func compareTestStructData(c1, c2 testStructData) bool { return c1 == c2}
复制代码


性能提升还是很明显的


➜  unique git:(master) ✗ /Users/hxzhouh/workspace/googlesource/go/bin/go test -bench='BenchmarkMake1' -count=5 goos: darwingoarch: arm64pkg: uniquecpu: Apple M1 ProBenchmarkMake1-10       122033748                9.692 ns/opBenchmarkMake1-10       123878858                9.688 ns/opBenchmarkMake1-10       123927121                9.706 ns/opBenchmarkMake1-10       123849468                9.759 ns/opBenchmarkMake1-10       123306187                9.673 ns/opPASSok      unique  11.055s➜  unique git:(master) ✗ /Users/hxzhouh/workspace/googlesource/go/bin/go test -bench='BenchmarkMake2' -count=5goos: darwingoarch: arm64pkg: uniquecpu: Apple M1 ProBenchmarkMake2-10       1000000000               0.3118 ns/opBenchmarkMake2-10       1000000000               0.3114 ns/opBenchmarkMake2-10       1000000000               0.3119 ns/opBenchmarkMake2-10       1000000000               0.3136 ns/opBenchmarkMake2-10       1000000000               0.3115 ns/opPASSok      unique  1.875s
复制代码


但是 你不应该把他当作一个全局变量来用,存储共享数据,unique 的底层实现其实是一个 map,查询的成本也是很高的。

比如

package huizhou92
import ( "testing" "unique")
var Token stringvar tokenUnique unique.Handle[string]
//go:noinlinefunc BusinessString(t string) bool { return t == Token}
//go:noinlinefunc BusinessUnique(t unique.Handle[string]) bool { return t.Value() == Token}func CreateString() string { t := make([]byte, 10e6) for i := 0; i < 10e6; i++ { t[i] = 'a' } return string(t)}
func init() { Token = CreateString() tokenUnique = unique.Make(Token)}
func BenchmarkBusinessString(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { BusinessString(Token) }}
func BenchmarkBusinessUnique(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { BusinessUnique(tokenUnique) }}
复制代码


➜  huizhou92_test git:(master) ✗ /Users/hxzhouh/workspace/googlesource/go/bin/go test --bench=BenchmarkBusinessUnique --count=5 goos: darwingoarch: arm64pkg: huizhou92_testcpu: Apple M1 ProBenchmarkBusinessUnique-10          3114            373867 ns/opBenchmarkBusinessUnique-10          3280            390818 ns/opBenchmarkBusinessUnique-10          2941            376503 ns/opBenchmarkBusinessUnique-10          3291            389665 ns/opBenchmarkBusinessUnique-10          2954            398610 ns/opPASSok      huizhou92_test  6.320s➜  huizhou92_test git:(master) ✗ /Users/hxzhouh/workspace/googlesource/go/bin/go test --bench=BenchmarkBusinessString --count=5 goos: darwingoarch: arm64pkg: huizhou92_testcpu: Apple M1 ProBenchmarkBusinessString-10      526721706                2.185 ns/opBenchmarkBusinessString-10      548612287                2.183 ns/opBenchmarkBusinessString-10      549425077                2.188 ns/opBenchmarkBusinessString-10      549012100                2.182 ns/opBenchmarkBusinessString-10      548929644                2.183 ns/opPASSok      huizhou92_test  7.237s
复制代码


正是因为这样,关于 unique 的讨论其实还在继续,可能是因为用到的地方不是很多?不管怎么样, 这个新的包进入标准库已经是事实了。 net/netip 已经用 unique 重构了它,用来比对 IP 地址的详细信息。


发布于: 刚刚阅读数: 3
用户头像

huizhou92

关注

种一棵树,最好的时间是十年前,其次是现在 2018-03-09 加入

还未添加个人简介

评论

发布
暂无评论
Golang 1.23: 新的 unique 包_huizhou92_InfoQ写作社区