Slice的内存使用情况不是我所期望的

问题描述 投票:0回答:1

我有一个简单的函数,我为此编写了基准。我试图理解为什么一种实现每个操作比其他实现使用更多的字节,却减少了内存分配。

下面的实现每次分配使用疯狂的字节数,我不明白为什么要做的就是对索引进行更新

type Tags []string

BenchmarkTags_Pair2-12        241742         98126 ns/op      850149 B/op          1 allocs/op

func (t Tags) Pair() []string {
    if len(t)&1 == 1 {
        return t
    }
    for i := 0; i < len(t)/2; i++ {
        // update at index
        t[i] = t[i*2] + ":" + t[i*2+1]
    }
    return t[:len(t)/2]
}

第二个实现几乎相同,但是创建了一个数组,并向其中添加了项

BenchmarkTags_Pair2-12      14231110            71.2 ns/op        32 B/op          2 allocs/op

func (t Tags) Pair() []string {
    if len(t)&1 == 1 {
        return t
    }
    // new array created
    tag := make([]string, len(t)/2)
    for i := 0; i < len(t)/2; i++ {
        // update at index
        tag[i] = t[i*2] + ":" + t[i*2+1]
    }
    return tag
}

我希望最上面的实现比第二个实现更快,并且需要更少的分配。

下面的基准功能,使用:

  • 转到1.14
  • goos:达尔文
  • goarch:amd64
  • 2.6 GHz 6核Intel Core i7
  • 16 GB 2400 MHz DDR4

列表项

func BenchmarkTags_Pair2(b *testing.B) {
            tags := Tags([]string{"network", "foobar"})
            var n []string
            _ = n
            b.ResetTimer()
            for i := 0; i < b.N; i++ {
                n = tags.Pair()
            }
        }

有人知道这里发生了什么吗?我不明白为什么在第一个实现中每个操作的字节会这么高。当我使用pprof进行检查时,我可以看到发生了gb的分配,并且GC的工作非常辛苦。

go memory slice
1个回答
0
投票

我没有找到任何原因的解释,但这肯定会发生,因为在第一个工作台中您正在修改方法接收器,而在第二个工作台中您只是在修改堆栈中分配的新切片。

我假设发生这种情况是因为t在堆中已修改,而tag在堆中已修改。

© www.soinside.com 2019 - 2024. All rights reserved.