mirror of https://github.com/golang/go.git
runtime: implement addrRanges.findSucc with a binary search
This change modifies addrRanges.findSucc to more efficiently find the successor range in an addrRanges by using a binary search to narrow down large addrRanges and iterate over no more than 8 addrRanges. This change makes the runtime more robust against systems that may aggressively randomize the address space mappings it gives the runtime (e.g. Fuchsia). For #40191. Change-Id: If529df2abd2edb1b1496d8690ddd284ecd7138c2 Reviewed-on: https://go-review.googlesource.com/c/go/+/242679 Trust: Michael Knyszek <mknyszek@google.com> Reviewed-by: Austin Clements <austin@google.com> Reviewed-by: Michael Pratt <mpratt@google.com>
This commit is contained in:
parent
0eb52ac250
commit
76bce1dd52
|
|
@ -172,20 +172,46 @@ func (a *addrRanges) init(sysStat *sysMemStat) {
|
||||||
a.totalBytes = 0
|
a.totalBytes = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// findSucc returns the first index in a such that base is
|
// findSucc returns the first index in a such that addr is
|
||||||
// less than the base of the addrRange at that index.
|
// less than the base of the addrRange at that index.
|
||||||
func (a *addrRanges) findSucc(addr uintptr) int {
|
func (a *addrRanges) findSucc(addr uintptr) int {
|
||||||
// TODO(mknyszek): Consider a binary search for large arrays.
|
|
||||||
// While iterating over these ranges is potentially expensive,
|
|
||||||
// the expected number of ranges is small, ideally just 1,
|
|
||||||
// since Go heaps are usually mostly contiguous.
|
|
||||||
base := offAddr{addr}
|
base := offAddr{addr}
|
||||||
for i := range a.ranges {
|
|
||||||
|
// Narrow down the search space via a binary search
|
||||||
|
// for large addrRanges until we have at most iterMax
|
||||||
|
// candidates left.
|
||||||
|
const iterMax = 8
|
||||||
|
bot, top := 0, len(a.ranges)
|
||||||
|
for top-bot > iterMax {
|
||||||
|
i := ((top - bot) / 2) + bot
|
||||||
|
if a.ranges[i].contains(base.addr()) {
|
||||||
|
// a.ranges[i] contains base, so
|
||||||
|
// its successor is the next index.
|
||||||
|
return i + 1
|
||||||
|
}
|
||||||
|
if base.lessThan(a.ranges[i].base) {
|
||||||
|
// In this case i might actually be
|
||||||
|
// the successor, but we can't be sure
|
||||||
|
// until we check the ones before it.
|
||||||
|
top = i
|
||||||
|
} else {
|
||||||
|
// In this case we know base is
|
||||||
|
// greater than or equal to a.ranges[i].limit-1,
|
||||||
|
// so i is definitely not the successor.
|
||||||
|
// We already checked i, so pick the next
|
||||||
|
// one.
|
||||||
|
bot = i + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// There are top-bot candidates left, so
|
||||||
|
// iterate over them and find the first that
|
||||||
|
// base is strictly less than.
|
||||||
|
for i := bot; i < top; i++ {
|
||||||
if base.lessThan(a.ranges[i].base) {
|
if base.lessThan(a.ranges[i].base) {
|
||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return len(a.ranges)
|
return top
|
||||||
}
|
}
|
||||||
|
|
||||||
// findAddrGreaterEqual returns the smallest address represented by a
|
// findAddrGreaterEqual returns the smallest address represented by a
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue