From d7a38adf4c81f0fa83203e37844192182b22680a Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Fri, 15 Aug 2025 17:09:05 +0000 Subject: runtime: eliminate global span queue [green tea] This change removes the locked global span queue and replaces the fixed-size local span queue with a variable-sized local span queue. The variable-sized local span queue grows as needed to accomodate local work. With no global span queue either, GC workers balance work amongst themselves by stealing from each other. The new variable-sized local span queues are inspired by the P-local deque underlying sync.Pool. Unlike the sync.Pool deque, however, both the owning P and stealing Ps take spans from the tail, making this incarnation a strict queue, not a deque. This is intentional, since we want a queue-like order to encourage objects to accumulate on each span. These variable-sized local span queues are crucial to mark termination, just like the global span queue was. To avoid hitting the ragged barrier too often, we must check whether any Ps have any spans on their variable-sized local span queues. We maintain a per-P atomic bitmask (another pMask) that contains this state. We can also use this to speed up stealing by skipping Ps that don't have any local spans. The variable-sized local span queues are slower than the old fixed-size local span queues because of the additional indirection, so this change adds a non-atomic local fixed-size queue. This risks getting work stuck on it, so, similarly to how workbufs work, each worker will occasionally dump some spans onto its local variable-sized queue. This scales much more nicely than dumping to a global queue, but is still visible to all other Ps. For #73581. Change-Id: I814f54d9c3cc7fa7896167746e9823f50943ac22 Reviewed-on: https://go-review.googlesource.com/c/go/+/700496 Reviewed-by: Michael Pratt LUCI-TryBot-Result: Go LUCI --- src/runtime/export_test.go | 24 ------------------------ 1 file changed, 24 deletions(-) (limited to 'src/runtime/export_test.go') diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index 607281d382..2a70111568 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -1289,30 +1289,6 @@ func MSpanCountAlloc(ms *MSpan, bits []byte) int { return result } -type MSpanQueue mSpanQueue - -func (q *MSpanQueue) Size() int { - return (*mSpanQueue)(q).n -} - -func (q *MSpanQueue) Push(s *MSpan) { - (*mSpanQueue)(q).push((*mspan)(s)) -} - -func (q *MSpanQueue) Pop() *MSpan { - s := (*mSpanQueue)(q).pop() - return (*MSpan)(s) -} - -func (q *MSpanQueue) TakeAll(p *MSpanQueue) { - (*mSpanQueue)(q).takeAll((*mSpanQueue)(p)) -} - -func (q *MSpanQueue) PopN(n int) MSpanQueue { - p := (*mSpanQueue)(q).popN(n) - return (MSpanQueue)(p) -} - const ( TimeHistSubBucketBits = timeHistSubBucketBits TimeHistNumSubBuckets = timeHistNumSubBuckets -- cgit v1.3-5-g9baa