go-critic icon indicating copy to clipboard operation
go-critic copied to clipboard

Optimize cases of clearing maps

Open breml opened this issue 6 years ago • 5 comments
trafficstars

Since merge of 110055 (Issue: go#20138, the clearing of maps (that is, delete all key/values from the map such that is empty) with a for ... range loop has been implemented in the compiler to emit optimized code. So go-critic could detect respective cases and suggest the necessary fix.

Before:

m = map[K]V{}

After:

for k := range m {
    delete(m, k)
}

breml avatar Mar 31 '19 18:03 breml

I think the second form can take more CPU time. Need to check it out though. Never done any real measurements of this.

quasilyte avatar Mar 31 '19 18:03 quasilyte

Based on the benchamrks in 110055 I think it is the oposite. As said, the for ... range is detected by the compiler and replaced with highly optimized code to clear the map. The main advantage of this is, that there is no new allocation, which in fact has a positive effect on the GC.

Of course, we should also detect m = make(map[K]V).

breml avatar Mar 31 '19 18:03 breml

The difficult part maybe is to detect cases, where m is in fact not nil before the assignment of the new map.

breml avatar Mar 31 '19 18:03 breml

I heard that there is something like memory/CPU time trade-off there anyway. For empty map literal there is only a (quite fast) allocation while clearing a huge map still requires to walk buckets and clearing them.

quasilyte avatar Mar 31 '19 19:03 quasilyte

The difficult part maybe is to detect cases, where m is in fact not nil before the assignment of the new map.

I wonder whether there is a pass in go/analysis that can help with this. Probably something from nillness pass maybe. Although I haven't really looked at it. Maybe it doesn't return any "facts" after analysis for other passes. Anyway, if we can find a way to get that info for the checker, it would be a much easier task.

quasilyte avatar Dec 19 '19 20:12 quasilyte