Skip to content

Commit

Permalink
cmd/viewcore: handle 1.14 free spans
Browse files Browse the repository at this point in the history
Free spans are now implicit. Derive the free span information
by finding all the memory in the inuse address ranges that isn't
attributed to any span.

Fixes viewcore for all versions of 1.14.
Also works for tip.

Fixes golang/go#38638

Change-Id: Ied283f59391aad8ed5b1b657d2fd6e89e9e9ae6c
  • Loading branch information
randall77 committed May 5, 2020
1 parent a1fc89a commit 50bc1c4
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 1 deletion.
1 change: 1 addition & 0 deletions internal/gocore/gocore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,4 +270,5 @@ func TestVersions(t *testing.T) {
loadExampleVersion(t, "1.12.zip")
loadExampleVersion(t, "1.13.zip")
loadExampleVersion(t, "1.13.3.zip")
loadExampleVersion(t, "1.14.zip")
}
48 changes: 47 additions & 1 deletion internal/gocore/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ func (p *Process) readSpans(mheap region, arenas []arena) {
panic("weird mapping " + m.Perm().String())
}
}
if mheap.HasField("curArena") {
if mheap.HasField("curArena") { // go1.13.3 <= x < go1.14
// Subtract from the heap unallocated space
// in the current arena.
ca := mheap.Field("curArena")
Expand Down Expand Up @@ -431,6 +431,52 @@ func (p *Process) readSpans(mheap region, arenas []arena) {
}
}
}
if mheap.HasField("pages") { // go1.14+
// There are no longer "free" mspans to represent unused pages.
// Instead, there are just holes in the pagemap into which we can allocate.
// Look through the in-use ranges, and figure out how much is before and
// after the scavenge address.
pages := mheap.Field("pages")
// Regions below scavAddr are unscavenged.
// Regions above scavAddr are scavenged.
scavAddr := core.Address(pages.Field("scavAddr").Uintptr())
inuse := pages.Field("inUse")
ranges := inuse.Field("ranges")
scavenged := int64(0)
unscavenged := int64(0)
for i := int64(0); i < ranges.SliceLen(); i++ {
r := ranges.SliceIndex(i)
base := core.Address(r.Field("base").Uintptr())
limit := core.Address(r.Field("limit").Uintptr())
if limit <= scavAddr {
unscavenged += int64(limit - base)
} else if scavAddr <= base {
scavenged += int64(limit - base)
} else {
unscavenged += int64(scavAddr - base)
scavenged += int64(limit - scavAddr)
}
}
// Go through all the spans, subtracting the memory they use.
// Whatever remains are free spans.
for i := int64(0); i < n; i++ {
s := allspans.SliceIndex(i).Deref()
min := core.Address(s.Field("startAddr").Uintptr())
nPages := int64(s.Field("npages").Uintptr())
spanSize := nPages * pageSize
max := min.Add(spanSize)
if max <= scavAddr {
unscavenged -= int64(max - min)
} else if scavAddr <= min {
scavenged -= int64(max - min)
} else {
unscavenged -= int64(scavAddr - min)
scavenged -= int64(max - scavAddr)
}
}
freeSpanSize = scavenged + unscavenged
releasedSpanSize = scavenged
}

p.stats = &Stats{"all", all, []*Stats{
&Stats{"text", text, nil},
Expand Down
Binary file added internal/gocore/testdata/1.14.zip
Binary file not shown.

0 comments on commit 50bc1c4

Please sign in to comment.