select + time.After 导致内存暴涨#
func Function(notRun notRun) {
for {
select {
case <-notRun.notRun:
// 大多数情况都是有notRun的输入
case <-time.After(time.Minute):
notRun.Close()
continue
case <-notRun.run:
notRun.Close()
return
}
}
}
- notRun 发送消息频率过快,而每次select都会调用到time.After,而time.After又会NewTimer,而每次NewTimer都必须在1分钟后才能释放。
- 当notRun的频率很高时,会在内存中堆积非常多的无用的Timer。导致内存暴涨。
解决方法#
func Function(notRun notRun) {
afterTime := time.Minute
after := time.NewTimer(afterTime)
defer after.Stop()
for {
after.Reset(afterTime)
select {
case <-notRun.notRun:
case <-after.C:
notRun.Close()
continue
case <-notRun.run:
notRun.Close()
return
}
}
}
- 自己 NewTimer 在每次 select 之前 reset,使 timer 重新计时,从而避免每次都 new timer。