返回介绍

上卷 程序设计

中卷 标准库

下卷 运行时

源码剖析

附录

5.4.1 性能

发布于 2024-10-12 19:15:47 字数 2507 浏览 0 评论 0 收藏 0

预分配足够空间有助于提升性能,减少因扩张引发的内存分配和数据迁移操作。

package main

import (
	"testing"
)

const max = 10000

//go:noinline
func test(cap int) map[int]int {
	m := make(map[int]int, cap)
    
	for i := 0; i < max; i++ {
		m[i] = i
	}
    
	return m
}

// -------------------------------

func BenchmarkTest(b *testing.B) {
	for i := 0; i < b.N; i++ {
		test(0)
	}
}

func BenchmarkTestCap(b *testing.B) {
	for i := 0; i < b.N; i++ {
		test(max)
	}
}

/*

$ go test -bench . -benchmem

cpu: Intel(R) Core(TM) i5-5257U CPU @ 2.70GHz

BenchmarkTest-2      943   1091463 ns/op   687253 B/op   278 allocs/op
BenchmarkTestCap-2  2242    567812 ns/op   322285 B/op    12 allocs/op

*/

字典内联存储有长度限制。如果超出,则重新分配内存并复制。

提示:1.18 上限是 128 字节。详情请阅读《下卷:8.4 字典》。

package main

import (
	"testing"
)

const max = 100

//go:noinline
func test[T any](v T) map[int]T {
	m := make(map[int]T, max)

	for i := 0; i < max; i++ {
		m[i] = v
	}

	return m
}

// -------------------------------

func Benchmark128(b *testing.B) {
	for i := 0; i < b.N; i++ {
		test([128]byte{1,2,3})
	}
}

func Benchmark129(b *testing.B) {
	for i := 0; i < b.N; i++ {
		test([129]byte{1,2,3})
	}
}

/*

$ go test -bench . -benchmem

Benchmark128-2     106706   11268 ns/op   21270 B/op     8 allocs/op
Benchmark129-2      78174   13199 ns/op   17288 B/op   103 allocs/op

*/

扩张的内存不会因键值删除而收缩,必要时应新建字典。

package main

import (
	"runtime"
	"time"
)

const max = 1000000

//go:noinline
func test[T any](v T) map[int]T {
	m := make(map[int]T, max)

	for i := 0; i < max; i++ {
		m[i] = v
	}

	return m
}


func main() {
	m := test([128]byte{1,2,3})
	// m := test([128 + 1]byte{1,2,3})

	runtime.GC()

	clear(m)

	for i := 0; i < 5; i++ {
		time.Sleep(time.Second)
		runtime.GC()
	}

	runtime.KeepAlive(&m)
}

/*

$ go build && GODEBUG=gctrace=1 ./test

--- 128 -----------------

内联:字典内存无法收缩,时间较短。

gc 2 @1.023s 0%: 293->293->293 MB, (forced)
gc 3 @2.061s 0%: 293->293->293 MB, (forced)
gc 4 @3.066s 0%: 293->293->293 MB, (forced)
gc 5 @4.073s 0%: 293->293->293 MB, (forced)
gc 6 @5.076s 0%: 293->293->293 MB, (forced)

--- 128 + 1 -------------

外联:外部对象被回收,时间较长。

gc 4 @0.335s 15%: 175->175->175 MB, (forced)
gc 5 @1.420s  4%: 175->175->38  MB, (forced)
gc 6 @2.452s  2%: 38->38->38    MB, (forced)
gc 7 @3.474s  1%: 38->38->38    MB, (forced)
gc 8 @4.497s  1%: 38->38->38    MB, (forced)

*/

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文