mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
runtime: do not scan maps when k/v do not contain pointers
Currently we scan maps even if k/v does not contain pointers. This is required because overflow buckets are hanging off the main table. This change introduces a separate array that contains pointers to all overflow buckets and keeps them alive. Buckets themselves are marked as containing no pointers and are not scanned by GC (if k/v does not contain pointers). This brings maps in line with slices and chans -- GC does not scan their contents if elements do not contain pointers. Currently scanning of a map[int]int with 2e8 entries (~8GB heap) takes ~8 seconds. With this change scanning takes negligible time. Update #9477. Change-Id: Id8a04066a53d2f743474cad406afb9f30f00eaae Reviewed-on: https://go-review.googlesource.com/3288 Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
561ce92fa0
commit
85e7bee19f
3 changed files with 110 additions and 35 deletions
|
|
@ -1469,9 +1469,8 @@ func MapOf(key, elem Type) Type {
|
|||
|
||||
// Make a map type.
|
||||
var imap interface{} = (map[unsafe.Pointer]unsafe.Pointer)(nil)
|
||||
prototype := *(**mapType)(unsafe.Pointer(&imap))
|
||||
mt := new(mapType)
|
||||
*mt = *prototype
|
||||
*mt = **(**mapType)(unsafe.Pointer(&imap))
|
||||
mt.string = &s
|
||||
mt.hash = fnv1(etyp.hash, 'm', byte(ktyp.hash>>24), byte(ktyp.hash>>16), byte(ktyp.hash>>8), byte(ktyp.hash))
|
||||
mt.key = ktyp
|
||||
|
|
@ -1575,7 +1574,7 @@ func (gc *gcProg) appendProg(t *rtype) {
|
|||
for i := 0; i < c; i++ {
|
||||
gc.appendProg(t.Field(i).Type.common())
|
||||
}
|
||||
if gc.size > oldsize + t.size {
|
||||
if gc.size > oldsize+t.size {
|
||||
panic("reflect: struct components are larger than the struct itself")
|
||||
}
|
||||
gc.size = oldsize + t.size
|
||||
|
|
@ -1650,6 +1649,12 @@ const (
|
|||
)
|
||||
|
||||
func bucketOf(ktyp, etyp *rtype) *rtype {
|
||||
// See comment on hmap.overflow in ../runtime/hashmap.go.
|
||||
var kind uint8
|
||||
if ktyp.kind&kindNoPointers != 0 && etyp.kind&kindNoPointers != 0 {
|
||||
kind = kindNoPointers
|
||||
}
|
||||
|
||||
if ktyp.size > maxKeySize {
|
||||
ktyp = PtrTo(ktyp).(*rtype)
|
||||
}
|
||||
|
|
@ -1679,6 +1684,7 @@ func bucketOf(ktyp, etyp *rtype) *rtype {
|
|||
|
||||
b := new(rtype)
|
||||
b.size = gc.size
|
||||
b.kind = kind
|
||||
b.gc[0], _ = gc.finalize()
|
||||
s := "bucket(" + *ktyp.string + "," + *etyp.string + ")"
|
||||
b.string = &s
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue