golang 的 gc 从实践来看弱爆了, while { readline, } 处理大文本很快内存消耗完, 大量 cpu 时间消耗到 gc 上。 下面两个工具可以缓解这种问题, 一是一块 buffer 上用多个 slice 连续存储, 另一个是自动缩放的一块 buffer 存变长的值。
type BytesPool struct {
Buffer []byte
Index int
Top int
}
//size, initial pool size
func NewBytesPool(size int) *BytesPool {
return &BytesPool{make([]byte, size), 0, 0}
}
//get slice
func (b *BytesPool) AllocSlice(size int) []byte {
//expand 1.5x
if len(b.Buffer) < size + b.Index {
nb := make([]byte, int(float64(len(b.Buffer)) * 1.5) + size)
copy(nb, b.Buffer)
b.Buffer = nb
}
slice := b.Buffer[b.Index:b.Index+size]
b.Top = b.Index
b.Index += size
return slice
}
func (b *BytesPool) GetSlice() []byte {
return b.Buffer[b.Top:b.Index]
}
type AutoResizeByteArray struct {
Buffer []byte
Top int
}
func NewAutoResizeByteArray(size int) *AutoResizeByteArray {
return &AutoResizeByteArray{make([]byte, size), 0}
}
func (b *AutoResizeByteArray) AllocSlice(size int) []byte {
if len(b.Buffer) < size {
nb := make([]byte, int(float64(len(b.Buffer)) * 1.5) + size)
copy(nb, b.Buffer)
b.Buffer = nb
}
b.Top = size
return b.Buffer[:size]
}
func (b *AutoResizeByteArray) GetSlice() []byte {
return b.Buffer[:b.Top]
}
func testBytesPool() {
b := NewBytesPool(3)
copy(b.AllocSlice(4), []byte("abcd"))
fmt.Printf("%s\n", b.GetSlice())
copy(b.AllocSlice(2), []byte("ef"))
fmt.Printf("%s\n", b.GetSlice())
b1 := NewAutoResizeByteArray(3)
copy(b1.AllocSlice(4), []byte("abcd"))
fmt.Printf("%s\n", b1.GetSlice())
}
大家还有什么好注意? 欢迎交流。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.