From: Michael Anthony Knyszek Date: Tue, 16 Jul 2019 20:36:33 +0000 (+0000) Subject: runtime: add physHugePageShift X-Git-Tag: go1.13rc1~62 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=a41ebe6e259af020d4ce7029544439b39d07936b;p=gostls13.git runtime: add physHugePageShift This change adds physHugePageShift which is defined such that 1 << physHugePageShift == physHugePageSize. The purpose of this variable is to avoid doing expensive divisions in key functions, such as (*mspan).hugePages. This change also does a sweep of any place we might do a division or mod operation with physHugePageSize and turns it into bit shifts and other bitwise operations. Finally, this change adds a check to mallocinit which ensures that physHugePageSize is always a power of two. osinit might choose to ignore non-powers-of-two for the value and replace it with zero, but mallocinit will fail if it's not a power of two (or zero). It also derives physHugePageShift from physHugePageSize. This change helps improve the performance of most applications because of how often (*mspan).hugePages is called. Updates #32828. Change-Id: I1a6db113d52d563f59ae8fd4f0e130858859e68f Reviewed-on: https://go-review.googlesource.com/c/go/+/186598 Run-TryBot: Austin Clements TryBot-Result: Gobot Gobot Reviewed-by: Austin Clements --- diff --git a/src/runtime/malloc.go b/src/runtime/malloc.go index 5a21e80e18..d768054198 100644 --- a/src/runtime/malloc.go +++ b/src/runtime/malloc.go @@ -325,12 +325,21 @@ const ( var physPageSize uintptr // physHugePageSize is the size in bytes of the OS's default physical huge -// page size whose allocation is opaque to the application. +// page size whose allocation is opaque to the application. It is assumed +// and verified to be a power of two. // // If set, this must be set by the OS init code (typically in osinit) before // mallocinit. However, setting it at all is optional, and leaving the default // value is always safe (though potentially less efficient). -var physHugePageSize uintptr +// +// Since physHugePageSize is always assumed to be a power of two, +// physHugePageShift is defined as physHugePageSize == 1 << physHugePageShift. +// The purpose of physHugePageShift is to avoid doing divisions in +// performance critical functions. +var ( + physHugePageSize uintptr + physHugePageShift uint +) // OS memory management abstraction layer // @@ -432,6 +441,17 @@ func mallocinit() { print("system page size (", physPageSize, ") must be a power of 2\n") throw("bad system page size") } + if physHugePageSize&(physHugePageSize-1) != 0 { + print("system huge page size (", physHugePageSize, ") must be a power of 2\n") + throw("bad system huge page size") + } + if physHugePageSize != 0 { + // Since physHugePageSize is a power of 2, it suffices to increase + // physHugePageShift until 1<= totalWork { - hugePages := totalWork / uint64(physHugePageSize) - hugeWork = hugePages * uint64(physHugePageSize) + hugePages := totalWork >> physHugePageShift + hugeWork = hugePages << physHugePageShift } // Everything that's not huge work is regular work. At this point we // know huge work so we can calculate how much time that will take // based on scavengePageRate (which applies to pages of any size). regularWork = totalWork - hugeWork - hugeTime = hugeWork / uint64(physHugePageSize) * scavengeHugePagePeriod + hugeTime = (hugeWork >> physHugePageShift) * scavengeHugePagePeriod } // Finally, we can compute how much time it'll take to do the regular work // and the total time to do all the work. diff --git a/src/runtime/mheap.go b/src/runtime/mheap.go index af2818a2bd..91ad47bdd0 100644 --- a/src/runtime/mheap.go +++ b/src/runtime/mheap.go @@ -561,7 +561,7 @@ func (s *mspan) hugePages() uintptr { end &^= physHugePageSize - 1 } if start < end { - return (end - start) / physHugePageSize + return (end - start) >> physHugePageShift } return 0 }