golang切片分配性能

时间:2016-03-21 08:16:21

标签: performance memory go

我在GO中检查内存分配的性能时偶然发现了一件有趣的事情。

package main

import (
      "fmt"
      "time"
    )

func main(){
   const alloc int = 65536
   now := time.Now()
   loop := 50000
   for i := 0; i<loop;i++{
      sl := make([]byte, alloc)
      i += len(sl) * 0
   }
   elpased := time.Since(now)
   fmt.Printf("took %s to allocate %d bytes %d times", elpased, alloc, loop) 
}

我在Core-i7 2600上运行此版本,版本为1.6 64位(32位也是相同的结果)和16 GB RAM(在WINDOWS 10上) 因此当alloc为65536(正好是64K)时,它运行30秒(!!!!)。 当alloc为65535时,需要大约200ms。 有人可以向我解释一下吗? 我在家里用我的核心i7-920 @ 3.8GHZ尝试了相同的代码,但它没有显示相同的结果(两者都花了大约200ms)。任何人都知道发生了什么?

2 个答案:

答案 0 :(得分:5)

设置GOGC =关闭改进的性能(低至100ms)。为什么? 因为escape analysis。使用go build -gcflags -m构建时,编译器会打印任何分配到堆的分配。它真的取决于你的机器和GO编译器版本,但是当编译器决定分配应该移动到堆时,它意味着两件事: 1.分配将花费更长时间(因为&#34;在堆栈上分配&#34;只是1 cpu指令) 2. GC将不得不在以后清理该内存 - 耗费更多的CPU时间 对于我的机器,65536字节的分配转储到堆,65535不转移。 这就是为什么1个字节将整个过程从200ms改为30s的原因。惊人..

答案 1 :(得分:0)

原因很简单。

const alloc int = 65535

0x0000 00000 (example.go:8) TEXT "".main(SB), ABIInternal, $65784-0

const alloc int = 65536

0x0000 00000 (example.go:8) TEXT "".main(SB), ABIInternal, $248-0

区别在于创建切片的位置。