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
|
||||
}
|
||||
|
||||
// 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.
|
||||
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}
|
||||
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) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return len(a.ranges)
|
||||
return top
|
||||
}
|
||||
|
||||
// findAddrGreaterEqual returns the smallest address represented by a
|
||||
|
|
|
|||
Loading…
Reference in New Issue