From: Russ Cox Date: Thu, 14 May 2015 21:27:04 +0000 (-0400) Subject: runtime: allocate map element zero values for reflect-created types on demand X-Git-Tag: go1.5beta1~577 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=7e26a2d9a80b825d019c2cdaf6437d89001506a9;p=gostls13.git runtime: allocate map element zero values for reflect-created types on demand Preallocating them in reflect means that (1) if you say _ = PtrTo(ArrayOf(1000000000, reflect.TypeOf(byte(0)))), you just allocated 1GB of data (2) if you say it again, that's *another* GB of data. The only use of t.zero in the runtime is for map elements. Delay the allocation until the creation of a map with that element type, and share the zeros. The one downside of the shared zero is that it's not garbage collected, but it's also never written, so the OS should be able to handle it fairly efficiently. Change-Id: I56b098a091abf3ac0945de28ebef9a6c08e76614 Reviewed-on: https://go-review.googlesource.com/10111 Reviewed-by: Keith Randall --- diff --git a/src/reflect/type.go b/src/reflect/type.go index 5a43805626..bffe2595dd 100644 --- a/src/reflect/type.go +++ b/src/reflect/type.go @@ -1087,7 +1087,6 @@ func (t *rtype) ptrTo() *rtype { p.uncommonType = nil p.ptrToThis = nil - p.zero = unsafe.Pointer(&make([]byte, p.size)[0]) p.elem = t ptrMap.m[t] = p @@ -1467,7 +1466,6 @@ func ChanOf(dir ChanDir, t Type) Type { ch.elem = typ ch.uncommonType = nil ch.ptrToThis = nil - ch.zero = unsafe.Pointer(&make([]byte, ch.size)[0]) return cachePut(ckey, &ch.rtype) } @@ -1530,7 +1528,6 @@ func MapOf(key, elem Type) Type { mt.reflexivekey = isReflexive(ktyp) mt.uncommonType = nil mt.ptrToThis = nil - mt.zero = unsafe.Pointer(&make([]byte, mt.size)[0]) return cachePut(ckey, &mt.rtype) } @@ -1610,7 +1607,6 @@ func FuncOf(in, out []Type, variadic bool) Type { ft.string = &str ft.uncommonType = nil ft.ptrToThis = nil - ft.zero = unsafe.Pointer(&make([]byte, ft.size)[0]) funcLookupCache.m[hash] = append(funcLookupCache.m[hash], &ft.rtype) return ft @@ -1857,7 +1853,6 @@ func SliceOf(t Type) Type { slice.elem = typ slice.uncommonType = nil slice.ptrToThis = nil - slice.zero = unsafe.Pointer(&make([]byte, slice.size)[0]) return cachePut(ckey, &slice.rtype) } @@ -1913,10 +1908,6 @@ func ArrayOf(count int, elem Type) Type { array.fieldAlign = typ.fieldAlign array.uncommonType = nil array.ptrToThis = nil - if array.size > 0 { - zero := make([]byte, array.size) - array.zero = unsafe.Pointer(&zero[0]) - } array.len = uintptr(count) array.slice = slice.(*rtype) diff --git a/src/runtime/hashmap.go b/src/runtime/hashmap.go index 9ca33992bb..2b3af301b3 100644 --- a/src/runtime/hashmap.go +++ b/src/runtime/hashmap.go @@ -233,6 +233,9 @@ func makemap(t *maptype, hint int64, h *hmap, bucket unsafe.Pointer) *hmap { throw("need padding in bucket (value)") } + // make sure zero of element type is available. + mapzero(t.elem) + // find size parameter which will hold the requested # of elements B := uint8(0) for ; hint > bucketCnt && float32(hint) > loadFactor*float32(uintptr(1)<2GB zero on 32-bit machine + throw("map element too large") + } + } + zerobuf.p = (*byte)(persistentalloc(zerobuf.size, 64, &memstats.other_sys)) + } + atomicstorep(unsafe.Pointer(&t.zero), unsafe.Pointer(zerobuf.p)) + unlock(&zerobuf.lock) +}