在Go中,map[]struct{}在性能和内存消耗方面比map[]bool更好,时间上快了5%,内存消耗少了10%,尤其是在处理大型集合时。
众所周知,Go语言没有内置Set,因此开发人员使用map来模仿Set的行为。使用map来实现Set意味着map的值不重要,我们只需要关注键的存在。大多数情况下,人们可能会选择bool,因为它是内存消耗最少的类型之一,但在Go中,使用空结构体也是另一种选择。在本文中,我们将对它们进行基准测试,以查看是否有任何差异。
代码示例
为了获取足够的数据进行比较,我们首先声明不同类型的map,然后将其键从0设置到2²⁴-1,观察它需要多长时间和内存来完成。
我们可以使用golang中的内置基准机制来完成此操作。只需要几行代码就可以了:
package main
import (
"testing"
)
const it = uint(1 << 24)
func BenchmarkSetWithBoolValueWrite(b *testing.B) {
set := make(map[uint]bool)
for i := uint(0); i < it; i++ {
set[i] = true
}
}
func BenchmarkSetWithStructValueWrite(b *testing.B) {
set := make(map[uint]struct{})
for i := uint(0); i < it; i++ {
set[i] = struct{}{}
}
}
func BenchmarkSetWithInterfaceValueWrite(b *testing.B) {
set := make(map[uint]interface{})
for i := uint(0); i < it; i++ {
set[i] = struct{}{}
}
}
map[uint]interface{}
是一种预计速度较慢的特殊类型。
由于读取操作对于任何键的性能应该是相似的,因此在这里我们只对写入/设置操作进行基准测试。
以下命令可以生成统计数据:
GOMAXPROCS=1 go test -v -bench=. -count=3 -run=none -benchmem | tee bench.txt
# run `go get -u golang.org/x/perf/cmd/benchstat` if benchstat failed
benchstat bench.txt
现在让我们来检查结果。
结果
name time/op
SetWithBoolValueWrite 3.27s ± 0%
SetWithStructValueWrite 3.12s ± 0%
SetWithInterfaceValueWrite 5.96s ± 0%
name alloc/op
SetWithBoolValueWrite 884MB ± 0%
SetWithStructValueWrite 802MB ± 0%
SetWithInterfaceValueWrite 1.98GB ± 0%
从上面的结果来看,与大集合相比,*map[]struct{}*
时间快了 5%,内存消耗减少了 10% 。*map[]bool*
(使用map[]interface{}
是一场灾难,因为它增加了很多开销,几乎使时间和内存增加了一倍。)
结论
虽然map[]struct{}
速度更快,内存消耗更少,但在大Set上更明显。因此,如果您赶时间并且资源不是您最关心的问题,那么使用map[]bool
应该完全没问题。如果追求极致性能,key的类型是uint,更推荐bitset。
希望你喜欢这篇文章,欢迎点赞、关注、分享。
标签:map,struct,bool,内存,0%,Go From: https://blog.51cto.com/u_12409319/6218415