分配大数据块的巨大 GC 性能问题

我刚刚注意到,如果我在程序中分配了一个巨大的内存块。GC 会吃掉所有的程序时间。


这是POC。


https://gist.github.com/martende/252f403f0c17cb489de4


func main() {

    //////////////// !!!!!!!

    /* If I uncomment 2 lines below programm runs fast */

    nodesPool := make([]int, 300e6, 300e6)

    _ = nodesPool

    //////////////////////7


    file, _ := os.Open("result.txt")

    defer file.Close()


    reader := bufio.NewReader(file)


    var lastLinkIdx = 1 // Dont use first element use 0 as saver


    cnt:=  0

    totalB := 0


    for {

       l, err := reader.ReadString('\n')

       if err == io.EOF {

    fmt.Println("EOF")

        break

    }


    cnt+=1      

    totalB+=len(l)


    lines := strings.Split(l, ":")

    nodeId,_ := strconv.Atoi(lines[0])

    _ = nodeId


    linkIdsStr  := strings.Split(lines[1], ",")

    var ii = len(linkIdsStr)

    _ = ii

    /*      ... */

}


fmt.Println("pool ",cnt,totalB,lastLinkIdx)



}

我认为 GC 尝试以某种方式移动巨大的内存块,实际上是否可以从 GC 中分配内存但将 GC 留给所有其他库,因为即使 ReadLine 也需要它。


这是使用内存块进行分析。


Total: 1445 samples

     428  29.6%  29.6%      722  50.0% runtime.sweepone

     375  26.0%  55.6%      375  26.0% markroot

     263  18.2%  73.8%      263  18.2% runtime.xadd

     116   8.0%  81.8%      116   8.0% strings.Count

      98   6.8%  88.6%      673  46.6% strings.genSplit

      34   2.4%  90.9%       44   3.0% runtime.MSpan_Sweep

      25   1.7%  92.7%      729  50.4% MCentral_Grow

      17   1.2%  93.8%       19   1.3% syscall.Syscall

       9   0.6%  94.5%        9   0.6% runtime.memclr

       9   0.6%  95.1%        9   0.6% runtime.memmove

这是没有内存块的分析。


  98  27.0%  27.0%       98  27.0% strings.Count

  93  25.6%  52.6%      228  62.8% strings.genSplit

  45  12.4%  65.0%       45  12.4% scanblock

  24   6.6%  71.6%       28   7.7% runtime.MSpan_Sweep

  13   3.6%  75.2%       74  20.4% runtime.mallocgc

  12   3.3%  78.5%       12   3.3% runtime.memclr

   8   2.2%  80.7%        8   2.2% MHeap_ReclaimList

   8   2.2%  82.9%       11   3.0% syscall.Syscall

   6   1.7%  84.6%       44  12.1% MHeap_Reclaim

   6   1.7%  86.2%        6   1.7% markonly


泛舟湖上清波郎朗
浏览 178回答 1
1回答

哈士奇WWW

Go 团队的 Dmitry Vyukov说这是一个Go 运行时性能问题,你可以通过大量分配触发,作为一种解决方法,“你可以在大对象死后立即收集它,然后立即增加 GOGC .”从广义上讲,GitHub 问题表明运行时会创建大量内存管理结构(跨度),然后它会无限期地保留这些结构,并且必须在每次 GC 上进行扫描。根据问题标签,Go 1.5 的目标是修复。他的解决方法示例是:package mainimport (&nbsp; &nbsp; "runtime"&nbsp; &nbsp; "runtime/debug")var x = make([]byte, 1<<20)var y []bytevar z []bytefunc main() {&nbsp; &nbsp; y = make([]byte, 1<<30)&nbsp; &nbsp; y = nil&nbsp; &nbsp; runtime.GC()&nbsp; &nbsp; debug.SetGCPercent(1000)&nbsp; &nbsp; for i := 0; i < 1e6; i++ {&nbsp; &nbsp; &nbsp; &nbsp; z = make([]byte, 8192)&nbsp; &nbsp; }}(一些评论是关于一个完全不同的答案和代码示例,重点是避免我已经编辑掉的分配。没有办法“告诉”StackOverflow 这是一个新答案,所以它们仍然存在。)
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go