3 回答

TA贡献2011条经验 获得超2个赞
我无法重现您的基准...
package main_test
import (
"math/rand"
"testing"
)
func AddToSliceByValue(mySlice []int) {
for idx := range mySlice {
mySlice[idx]++
}
}
func AddToSliceByPointer(mySlice *[]int) {
for idx := range *mySlice {
(*mySlice)[idx]++
}
}
func BenchmarkAddByValue(b *testing.B) {
mySlice := rand.Perm(1000)
for n := 0; n < b.N; n++ {
AddToSliceByValue(mySlice)
}
}
func BenchmarkAddByPointer(b *testing.B) {
mySlice := rand.Perm(1000)
for n := 0; n < b.N; n++ {
AddToSliceByPointer(&mySlice)
}
}
$ go test -bench=. -benchmem -count=4
goos: linux
goarch: amd64
pkg: test/bencslice
BenchmarkAddByValue-4 3010280 385 ns/op 0 B/op 0 allocs/op
BenchmarkAddByValue-4 3118990 385 ns/op 0 B/op 0 allocs/op
BenchmarkAddByValue-4 3117450 384 ns/op 0 B/op 0 allocs/op
BenchmarkAddByValue-4 3109251 386 ns/op 0 B/op 0 allocs/op
BenchmarkAddByPointer-4 2012487 610 ns/op 0 B/op 0 allocs/op
BenchmarkAddByPointer-4 2009690 594 ns/op 0 B/op 0 allocs/op
BenchmarkAddByPointer-4 2009222 594 ns/op 0 B/op 0 allocs/op
BenchmarkAddByPointer-4 1850820 596 ns/op 0 B/op 0 allocs/op
PASS
ok test/bencslice 13.476s
$ go version
go version go1.15.2 linux/amd64
无论如何,行为可能取决于许多因素,首先是运行时的版本。只要您可以测试、重现和监控,了解内塞就没什么意义。

TA贡献1835条经验 获得超7个赞
我发现我的方差太高了:
AddByValue-12 5.41µs ±15%
AddByPointer-12 5.30µs ± 4%
我能够减少测试结果的go test -benchmem -count 5 -benchtime=1000000x -bench=. ./...方差,并且可以确认我的第一个假设,即结果应该大致相等:
AddByValue-12 5.04µs ± 1%
AddByPointer-12 5.17µs ± 1%
根据评论,高差异的主要原因是我没有在基准设置后重置计时器。
使用以下代码和较短的工作时间,我还减少了方差:
func BenchmarkAddByValue(b *testing.B) {
mySlice := rand.Perm(10000)
b.ResetTimer()
for n := 0; n < b.N; n++ {
AddToSliceByValue(mySlice)
}
}
func BenchmarkAddByPointer(b *testing.B) {
mySlice := rand.Perm(10000)
b.ResetTimer()
for n := 0; n < b.N; n++ {
AddToSliceByPointer(&mySlice)
}
}
结果:
AddByValue-12 5.03µs ± 0%
AddByPointer-12 5.17µs ± 1%
非常感谢你的帮助!

TA贡献1909条经验 获得超7个赞
这是“低级”语言的普遍问题。当您按值传递时,这意味着您实际上是在复制数据。这是它的工作原理。
当您通过引用传递时:
引用的副本被创建并传递给方法(引用很可能是 8 个字节,所以这很快)
你读出了引用后面的数据(这也很快,因为引用很可能在 CPU 缓存中)
在按值传递的情况下:
分配内存块来存储您传入的数据(慢)
数据被复制到新分配的内存块中(可能快,也可能慢)
然后通过引用访问您的数据(可能很慢,也可能很快,取决于数据是否在缓存中)
- 3 回答
- 0 关注
- 118 浏览
添加回答
举报