1. golang 的 gc 时机是根据当前与上次的 heap size 的比例来决定,默认情况下是100,即新增一倍就会触发。尝试把这个比例调大 export GOGC=400,有略微提升。
    refer ​​https://studygolang.com/articles/11159?fr=sidebar​
  2. 能返回实例值的函数就别返回指针。
    go里有独特的逃逸机制,指针的返回值一定会发生变量逃逸,逃逸的行为被理解为从栈中跑到了堆中,而堆中的gc是相对较慢的。返回值类型,会在内联处理后销毁,返回指针类型,会逃逸到堆上,增加gc压力。
    附带一个逃逸分析的指令:
    ​go build -gcflags '-m -m' x.go​
  3. 防止爆栈的几个场景
    在循环和递归里,出现的​​x:=1​​ 类似这样的临时变量会被存进栈中,只要不涉及到指针的逃逸,栈上的内存在该函数return后就会释放。那么如果是已知深度的循环(递归)内部,是不介意出现:=操作的。比如
for i:=1;i<100;i++{
tmp := t{}
}
return

相比于

var tmp t
for i:=1;i<100;i++{
tmp = t{}
}
return

差别其实不大,不过写成第二种方式依然是最干炼的。

但是在无法预估for 或者递归的深度时,如果深度很大,循环了千万次,依然是重点推荐第二种方法,虽然函数return后释放该函数在栈上开辟的变量,但是降低了爆栈的风险。

4.有人说函数返回时,内部的一些临时变量会被回收.有两个点。首先,golang 回收只发生在gc,函数结束时,只是标记一下,内存消耗依旧保留,不良的书写习惯造成高内耗,又增加gc频率,也就是stop world时间,非常的不值,贴一下两种写法的mem.rof 情况

对map插入十万条数据

golang 性能优化笔记(常更)_递归


golang 性能优化笔记(常更)_递归_02


golang 性能优化笔记(常更)_i++_03


golang 性能优化笔记(常更)_递归_04


差距还是蛮大的

最后pprof的链接,可以看一下这里

​​gc,cpu,heap,escape,服务器优化​