我刚刚注意到,如果我在程序中分配了一个巨大的内存块。GC 会吃掉所有的程序时间。这是POC。https://gist.github.com/martende/252f403f0c17cb489de4func 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
1 回答
哈士奇WWW
TA贡献1799条经验 获得超6个赞
Go 团队的 Dmitry Vyukov说这是一个Go 运行时性能问题,你可以通过大量分配触发,作为一种解决方法,“你可以在大对象死后立即收集它,然后立即增加 GOGC .”
从广义上讲,GitHub 问题表明运行时会创建大量内存管理结构(跨度),然后它会无限期地保留这些结构,并且必须在每次 GC 上进行扫描。根据问题标签,Go 1.5 的目标是修复。
他的解决方法示例是:
package main
import (
"runtime"
"runtime/debug"
)
var x = make([]byte, 1<<20)
var y []byte
var z []byte
func main() {
y = make([]byte, 1<<30)
y = nil
runtime.GC()
debug.SetGCPercent(1000)
for i := 0; i < 1e6; i++ {
z = make([]byte, 8192)
}
}
(一些评论是关于一个完全不同的答案和代码示例,重点是避免我已经编辑掉的分配。没有办法“告诉”StackOverflow 这是一个新答案,所以它们仍然存在。)
- 1 回答
- 0 关注
- 177 浏览
添加回答
举报
0/150
提交
取消