在golang中清除切片是否可以保证垃圾回收?

时间:2015-10-28 07:56:54

标签: go garbage-collection slice

我想使用golang切片实现基于时间的插槽来保存数据。我设法提出了这样的go程序,它也有效。但我对垃圾收集和该程序的一般性能几乎没有疑问。切片等于零时,此程序是否保证项目的垃圾收集?虽然洗牌,我希望这个程序不会进行任何深度复制。

type DataSlots struct {
    slotDuration  int //in milliseconds
    slots         [][]interface{}
    totalDuration int //in milliseconds
}

func New(slotDur int, totalDur int) *DataSlots {
    dat := &DataSlots{slotDuration: slotDur,
        totalDuration: totalDur}
    n := totalDur / slotDur
    dat.slots = make([][]interface{}, n)
    for i := 0; i < n; i++ {
        dat.slots[i] = make([]interface{}, 0)
    }
    go dat.manageSlots()
    return dat
}

func (self *DataSlots) addData(data interface{}) {
    self.slots[0] = append(self.slots[0], data)
}

// This should be a go routine
func (self *DataSlots) manageSlots() {
    n := self.totalDuration / self.slotDuration
    for {
        time.Sleep(time.Duration(self.slotDuration) * time.Millisecond)
        for i := n - 1; i > 0; i-- {
            self.slots[i] = self.slots[i-1]
        }
        self.slots[0] = nil
    }
}

我删除了此代码段中的关键部分处理,以使其简洁。

2 个答案:

答案 0 :(得分:5)

一旦切片设置得过nil,切片中包含的任何值都可用于垃圾回收,前提是底层数组不与另一个切片共享。

由于程序中没有切片操作,因此您永远不会对同一个数组进行多次引用,也不会将数据留在底层数组的任何不可访问的部分中。

您需要注意的是,当您使用切片操作时:

a := []int{1, 2, 3, 4}
b := a[1:3]
a = nil
// the values 1 and 4 can't be collected, because they are
// still contained in b's underlying array

c := []int{1, 2, 3, 4}
c = append(c[1:2], 5)
// c is now []int{2, 5}, but again the values 1 and 4 are
// still in the underlying array. The 4 may be overwritten
// by a later append, but the 1 is inaccessible and won't
// be collected until the underlying array is copied.

当切片的容量不足时,append会复制值,而只复制切片中包含的值。没有任何值的深层副本。

答案 1 :(得分:-1)

  

此程序是否保证切片一旦进行垃圾收集   等于零?

在某些时候是,但不是马上。

但尝试用以下方法加快收集:

import "runtime/debug"

...

debug.FreeOSMemory()

https://golang.org/pkg/runtime/debug/#FreeOSMemory

  

func FreeOSMemory()

     

FreeOSMemory强制进行垃圾收集   尝试将尽可能多的内存返回给操作系统   可能。 (即使没有调用它,运行时也会逐渐返回   内存到后台任务中的操作系统。)