Golang:&struct{} vs struct{} 应该如何选择?☺

2015-12-19 15:35:14 +08:00
 raincious

有两个数据结构( 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
}

他们的不同之处在于一个存的是structPointer,另一个存的是structValue

我做了一些测试,(似乎)表明使用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 的情况下)

感谢。

2135 次点击
所在节点    Go 编程语言
3 条回复
chzyer
2015-12-19 15:45:39 +08:00
一个值被传递的时候会被复制,也就是如果是指针,就复制指针,如果是 struct ,就复制整个 struct.
建立一个&struct{}会先建立一个 struct{},在建立一个指针指向他
遍历一个[]*struct{} 会访问一串连续的指针,访问每个指针的时候会随机访问到这个指针指向的地址, GC 也是一样的道理。
孰轻孰重,这个就要靠你自己去判断了。
comicfans44
2015-12-19 20:56:51 +08:00
在考虑性能的情况下,需要考虑你的使用模式是否是缓存友好的。
指针占用空间小,拷贝代价小,但是访问数据需要一次间接跳转,并不是缓存友好的。
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
CRVV
2015-12-20 12:01:56 +08:00
通常情况下,简单的回答是,如果 struct 很大,用指针更快,反之用值更快
但什么是 “很大”,显然不容易判断

所以我的观点是,上面说的都没什么用
如果要在意这个性能,就分别做性能测试,哪个快用哪个

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/244671

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX