You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
package main
type T struct {
p *int
i int
}
func f(m map[T]int) {
m[T{nil, 1}] = 1
m[T{nil, 2}] = 2
}
If you look at the disassembly of f, we use an autotmp to pass the key to mapassign. Each call to mapassign uses its own temporary. We should reuse these temporaries - they are live only for the duration of the mapassign call.
This situation gets particularly painful for large map initializations in init() functions. There could be thousands of mapassign calls, and each one gets its own temporary. That means really large stack frames and correspondingly large live pointer maps. In fact the live pointer map size is quadratic in source size, as it is proportional to both the number of temporaries and the number of safe points.
There are other places we use temporaries like this, mostly introduced in order.go. We should reuse temps for as many as we can.
Note: I use the weird key in the example to avoid the _fast version for int32, int64, and string. _fast versions don't use an autotmp.
I tried this when I was working on #19751 and found that it didn't help all that much; maybe I did it wrong though. It was also a pain to implement, due to how walk and sinit ping-pong back and forth--there was no good place to put state, but again, I'd be delighted to have been wrong about this.
If you look at the disassembly of
f
, we use an autotmp to pass the key to mapassign. Each call to mapassign uses its own temporary. We should reuse these temporaries - they are live only for the duration of the mapassign call.This situation gets particularly painful for large map initializations in init() functions. There could be thousands of mapassign calls, and each one gets its own temporary. That means really large stack frames and correspondingly large live pointer maps. In fact the live pointer map size is quadratic in source size, as it is proportional to both the number of temporaries and the number of safe points.
There are other places we use temporaries like this, mostly introduced in order.go. We should reuse temps for as many as we can.
Note: I use the weird key in the example to avoid the _fast version for
int32
,int64
, andstring
. _fast versions don't use an autotmp.Related: #19751
@josharian @mdempsky @martisch
The text was updated successfully, but these errors were encountered: