【发布时间】:2015-02-21 16:43:51
【问题描述】:
我经常使用结构切片。以下是此类结构的示例:
type MyStruct struct {
val1, val2, val3 int
text1, text2, text3 string
list []SomeType
}
所以我将切片定义如下:
[]MyStruct
假设我有大约一百万个元素,我正在大量使用切片:
- 我经常添加新元素。 (元素总数未知。)
- 我不时对其进行排序。
- 我还删除了元素(虽然不如添加新元素那么多)。
- 我经常阅读元素并将它们传递(作为函数参数)。
- 元素本身的内容不会改变。
我的理解是,这会导致实际结构的大量改组。另一种方法是创建一个指向结构的指针切片:
[]*MyStruct
现在结构保持在原来的位置,我们只处理我认为占用空间较小的指针,因此会使我的操作更快。但现在我要给垃圾收集器做更多的工作。
- 您能否提供有关何时直接使用结构与何时使用指向结构的指针的一般准则?
- 我应该担心留给 GC 的工作量吗?
- 复制结构与复制指针的性能开销是否可以忽略不计?
- 也许一百万个元素并不多。当切片变得更大时(当然,仍然适合 RAM),这一切会如何变化?
【问题讨论】:
-
您的示例结构是 12 个单词(每个 int 1 个,每个字符串 2 个,切片 3 个),指针是 1。这是我最关心的删除,因为平均每个都需要移位, 数组的一半。如果您可以通过将一个元素与切片中的最后一个元素交换并将切片缩小 1 或通过将结构字段或指针归零来删除一个元素,那么这些将是常量时间。如果结构较大并且您对数组做了很多工作,我的直觉也是指针。
-
FWIW,at the bottom here are some considerations for choosing between
[]Tand[]*T-- 大多数人在这里所说的重新hash,但也许还有其他一些因素(比如担心在append重新分配切片后保持指向切片的指针)。 -
感谢您的这些提示。最后的讨论(通过@twotwotwo)特别有用,因为它列出了需要注意的常见场景和陷阱。
标签: performance go slice