Skip to content

Commit 0b983ed

Browse files
mknyszeknebulabox
authored andcommitted
runtime: add credit system for scavenging
When scavenging small amounts it's possible we over-scavenge by a significant margin since we choose to scavenge the largest spans first. This over-scavenging is never accounted for. With this change, we add a scavenge credit pool, similar to the reclaim credit pool. Any time scavenging triggered by RSS growth starts up, it checks if it can cash in some credit first. If after using all the credit it still needs to scavenge, then any extra it does it adds back into the credit pool. This change mitigates the performance impact of golang.org/cl/159500 on the Garbage benchmark. On Go1 it suggests some improvements, but most of that is within the realm of noise (Revcomp seems very sensitive to GC-related changes, both postively and negatively). Garbage: https://perf.golang.org/search?q=upload:20190131.5 Go1: https://perf.golang.org/search?q=upload:20190131.4 Performance change with both changes: Garbage: https://perf.golang.org/search?q=upload:20190131.7 Go1: https://perf.golang.org/search?q=upload:20190131.6 Change-Id: I87bd3c183e71656fdafef94714194b9fdbb77aa2 Reviewed-on: https://go-review.googlesource.com/c/160297 Reviewed-by: Austin Clements <[email protected]>
1 parent df25424 commit 0b983ed

File tree

1 file changed

+21
-1
lines changed

1 file changed

+21
-1
lines changed

src/runtime/mheap.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,14 @@ type mheap struct {
107107
// This is accessed atomically.
108108
reclaimCredit uintptr
109109

110+
// scavengeCredit is spare credit for extra bytes scavenged.
111+
// Since the scavenging mechanisms operate on spans, it may
112+
// scavenge more than requested. Any spare pages released
113+
// go to this credit pool.
114+
//
115+
// This is protected by the mheap lock.
116+
scavengeCredit uintptr
117+
110118
// Malloc stats.
111119
largealloc uint64 // bytes allocated for large objects
112120
nlargealloc uint64 // number of large object allocations
@@ -165,7 +173,7 @@ type mheap struct {
165173
// simply blocking GC (by disabling preemption).
166174
sweepArenas []arenaIdx
167175

168-
_ uint32 // ensure 64-bit alignment of central
176+
// _ uint32 // ensure 64-bit alignment of central
169177

170178
// central free lists for small size classes.
171179
// the padding makes sure that the mcentrals are
@@ -1349,6 +1357,14 @@ func (h *mheap) freeSpanLocked(s *mspan, acctinuse, acctidle bool, unusedsince i
13491357
// starting from the largest span and working down. It then takes those spans
13501358
// and places them in scav. h must be locked.
13511359
func (h *mheap) scavengeLargest(nbytes uintptr) {
1360+
// Use up scavenge credit if there's any available.
1361+
if nbytes > h.scavengeCredit {
1362+
nbytes -= h.scavengeCredit
1363+
h.scavengeCredit = 0
1364+
} else {
1365+
h.scavengeCredit -= nbytes
1366+
return
1367+
}
13521368
// Iterate over the treap backwards (from largest to smallest) scavenging spans
13531369
// until we've reached our quota of nbytes.
13541370
released := uintptr(0)
@@ -1377,6 +1393,10 @@ func (h *mheap) scavengeLargest(nbytes uintptr) {
13771393
h.scav.insert(s)
13781394
released += r
13791395
}
1396+
// If we over-scavenged, turn that extra amount into credit.
1397+
if released > nbytes {
1398+
h.scavengeCredit += released - nbytes
1399+
}
13801400
}
13811401

13821402
// scavengeAll visits each node in the unscav treap and scavenges the

0 commit comments

Comments
 (0)