有两个数据结构( struct ),就像下面这样:
// 1
type Struct1 struct {
String string
}
type Structs1 []*Struct1 // Difference
type Test1Struct struct {
S Structs1
}
// 2
type Struct2 struct {
String string
}
type Structs2 []Struct2 // Difference
type Test2Struct struct {
S Structs2
}
他们的不同之处在于一个存的是struct
的Pointer
,另一个存的是struct
的Value
。
我做了一些测试,(似乎)表明使用Pointer
的时候要比使用Value
的时候更快:
[rain@localhost valuevspointor]$ go test -test.bench .
testing: warning: no tests to run
PASS
Benchmark1Pointer-2 5 229612872 ns/op
Benchmark2Value-2 1 1367639458 ns/op
Benchmark3HugeSetPointer-2 1 1100069534 ns/op
Benchmark4HugeSetValue-2 1 4037397573 ns/op
ok _/home/rain/Develpment/Meta/valuevspointor 10.775s
(当然这个测试说不定是有问题的,代码: https://gist.github.com/raincious/b70e17abfd08f4764683 )
按照上面的测试,想要建立一个新的 struct 应该优先使用&struct{}
而不是struct{}
,那么问题来了,如果是这样的话,struct{}
的意义何在?
或者应该问:如何决定应该使用&struct{}
还是struct{}
?
(比如在需要注意性能和 GC 的情况下)
感谢。
1
chzyer 2015-12-19 15:45:39 +08:00 1
一个值被传递的时候会被复制,也就是如果是指针,就复制指针,如果是 struct ,就复制整个 struct.
建立一个&struct{}会先建立一个 struct{},在建立一个指针指向他 遍历一个[]*struct{} 会访问一串连续的指针,访问每个指针的时候会随机访问到这个指针指向的地址, GC 也是一样的道理。 孰轻孰重,这个就要靠你自己去判断了。 |
2
comicfans44 2015-12-19 20:56:51 +08:00 2
在考虑性能的情况下,需要考虑你的使用模式是否是缓存友好的。
指针占用空间小,拷贝代价小,但是访问数据需要一次间接跳转,并不是缓存友好的。 struct 存在拷贝代价,但是使用时是缓存友好的。 在拥有多级缓存的现代 cpu 上,栈上的变量有很大可能完全位于缓存中,以至于小尺寸 struct 拷贝速度非常快。但指针所使用的内存可能并没有被预读到缓存中,这将导致使用指针变量反而更慢。 在这篇文章中有一段 https://talks.golang.org/2012/splash.article The key point is that Go gives the programmer tools to limit allocation by controlling the layout of data structures. Consider this simple type definition of a data structure containing a buffer (array) of bytes: type X struct { a, b, c int buf [256]byte } In Java, the buf field would require a second allocation and accesses to it a second level of indirection. In Go, however, the buffer is allocated in a single block of memory along with the containing struct and no indirection is required. For systems programming, this design can have a better performance as well as reducing the number of items known to the collector. At scale it can make a significant difference. 可以间接说明这个问题,通过指针间接访问变量是有代价的。 至于你的测试可能还不足以说明问题,因为 string 需要支持不同长度,肯定在内部实现上需要动态内存的,因此也就是一定存在间接访问。你需要做的测试需要对比 struct 成员全部是固定大小。一个紧凑的,连续累加 int 的测试或许可以有非常大的差异。至于指针更快还是 struct 更快取决于你的内存访问模式。如果是大数据(比如超过 cpu 二级缓存大小)拷贝为主,那就选指针。如果是连续访问元素,那么就应该选 struct |
3
CRVV 2015-12-20 12:01:56 +08:00 1
通常情况下,简单的回答是,如果 struct 很大,用指针更快,反之用值更快
但什么是 “很大”,显然不容易判断 所以我的观点是,上面说的都没什么用 如果要在意这个性能,就分别做性能测试,哪个快用哪个 |