分配未初始化的切片

时间:2013-06-24 12:47:14

标签: optimization initialization go

有没有办法在Go中分配未初始化的slice?一种常见的模式是创建给定大小的片作为缓冲区,然后仅将其中一部分用于receive数据。例如:

b := make([]byte, 0x20000) // b is zero initialized
n, err := conn.Read(b)
// do stuff with b[:n]. all of b is zeroed for no reason

这种初始化可以在分配大量缓冲区时加起来,因为spec表示默认情况下会在分配时初始化数组。

2 个答案:

答案 0 :(得分:2)

您可以从bufs.Cache.Get获取非归零字节缓冲区(或者参见CCache以获取并发安全版本)。来自docs

  

注意:Get 返回的缓冲区不保证归零。这对于例如将缓冲区传递给io.Reader。如果需要使用归零缓冲区,请使用Cget。

答案 1 :(得分:0)

从技术上讲,你可以通过在运行时之外分配内存并使用unsafe.Pointer,但这绝对是错误的。

更好的解决方案是减少分配数量。将缓冲区移到循环外部,或者,如果需要每个goroutine缓冲区,则在池中分配多个缓冲区,并在需要时分配更多缓冲区。

type BufferPool struct {
    Capacity int
    buffersize int
    buffers []byte
    lock sync.Mutex
}

func NewBufferPool(buffersize int, cap int) {
    ret := new(BufferPool)
    ret.Capacity = cap
    ret.buffersize = buffersize
    return ret
}

func (b *BufferPool) Alloc() []byte {
    b.lock.Lock()
    defer b.lock.Unlock()
    if len(b.buffers) == 0 {
        return make([]byte, b.buffersize)
    } else {
        ret := b.buffers[len(b.buffers) - 1]
        b.buffers = b.buffers[0:len(b.buffers) - 1]
        return ret
    }
}

func (b *BufferPool) Free(buf []byte) {
    if len(buf) != b.buffersize {
        panic("illegal free")
    }
    b.lock.Lock()
    defer b.lock.Unlock()
    if len(b.buffers) < b.Capacity {
        b.buffers = append(b.buffers, buf)
    }
}