【发布时间】:2017-08-09 07:07:14
【问题描述】:
我发现了什么:
我打印golang拷贝的时间成本,显示第一次内存拷贝很慢。但是即使我在不同的内存地址上运行“复制”,第二次也快得多。
这是我的测试代码:
func TestCopyLoop1x32M(t *testing.T) {
copyLoopSameDst(32*1024*1024, 1)
}
func TestCopyLoopOnex32M(t *testing.T) {
copyLoopSameDst(32*1024*1024, 1)
}
func copyLoopSameDst(size, loops int) {
in := make([]byte, size)
out := make([]byte, size)
rand.Seed(0)
fillRandom(in) // insert random byte into slice
now := time.Now()
for i := 0; i < loops; i++ {
copy(out, in)
}
cost := time.Since(now)
fmt.Println(cost.Seconds() / float64(loops))
}
func TestCopyDiffLoop1x32M(t *testing.T) {
copyLoopDiffDst(32*1024*1024, 1)
}
func copyLoopDiffDst(size, loops int) {
ins := make([][]byte, loops)
outs := make([][]byte, loops)
for i := 0; i < loops; i++ {
out := make([]byte, size)
outs[i] = out
in := make([]byte, size)
rand.Seed(0)
fillRandom(in)
ins[i] = in
}
now := time.Now()
for i := 0; i < loops; i++ {
copy(outs[i], ins[i])
}
cost := time.Since(now)
fmt.Println(cost.Seconds() / float64(loops))
}
结果(在 i5-4278U 上):
- 运行所有三个案例:
TestCopyLoop1x32M : 0.023s
TestCopyLoopOnex32M : 0.0038s
TestCopyDiffLoop1x32M : 0.0038s
- 运行第一种和第二种情况:
TestCopyLoop1x32M : 0.023s
TestCopyLoopOnex32M : 0.0038s
- 运行第一种和第三种情况:
TestCopyLoop1x32M : 0.023s
TestCopyLoop1x32M : 0.023s
我的问题:
他们有不同的内存地址和不同的数据,下一个案例如何从第一个案例中受益?
为什么 Result3 与 Result2 不同?他们不做同样的事情吗?
1234563 /li>
为什么“copyLoopDiffDst”在两个case后会加速?
我的猜测:
指令缓存有助于提高性能,但无法解释问题2
cpu 缓存的作用超出我的想象,但也无法解释问题2
【问题讨论】:
-
我对go一无所知,但如果你在函数内部动态创建和释放/释放,很可能当第二个函数想要写入数据时,它们已经在缓存。如果您想测试是否是这种情况,请尝试为这两个功能全局创建 2 个不同的输入/输出。这样第二个函数就没有上述优势了,你应该会看到减速
-
谢谢!在我将数据移出测试功能后,正如你所说,它变慢了。但是在我的代码中,“TestCopyLoop1x32M”和“TestCopyLoopOnex32M”做同样的事情,为什么只有第二个会有缓存?他们都在新的内存地址上创建了新数据,不是吗?
-
@IsuruH 谢谢你的想法。我想我已经找到了答案,但缓存的力量确实让我印象深刻。只有少数数据可能会发生写入命中,但它可以极大地提高性能
标签: performance caching go io cpu-cache