Skip to content

Commit 760ce2c

Browse files
sync: optimize pinslow
Change-Id: I0e12abb9bc848f6cb053f7b3d39beec65dadd967
1 parent 47dd861 commit 760ce2c

File tree

1 file changed

+31
-16
lines changed

1 file changed

+31
-16
lines changed

src/sync/pool.go

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package sync
66

77
import (
8+
"internal/cpu"
89
"internal/race"
910
"runtime"
1011
"sync/atomic"
@@ -76,6 +77,7 @@ type poolLocal struct {
7677
}
7778

7879
// from runtime
80+
//
7981
//go:linkname runtime_randn runtime.randn
8082
func runtime_randn(n uint32) uint32
8183

@@ -221,8 +223,9 @@ func (p *Pool) pinSlow() (*poolLocal, int) {
221223
// Retry under the mutex.
222224
// Can not lock the mutex while pinned.
223225
runtime_procUnpin()
224-
allPoolsMu.Lock()
225-
defer allPoolsMu.Unlock()
226+
a := &allPools[uintptr(unsafe.Pointer(p))%shardPoolsSize]
227+
a.lock.Lock()
228+
defer a.lock.Unlock()
226229
pid := runtime_procPin()
227230
// poolCleanup won't be called while we are pinned.
228231
s := p.localSize
@@ -231,7 +234,7 @@ func (p *Pool) pinSlow() (*poolLocal, int) {
231234
return indexLocal(l, pid), pid
232235
}
233236
if p.local == nil {
234-
allPools = append(allPools, p)
237+
a.s = append(a.s, p)
235238
}
236239
// If GOMAXPROCS changes between GCs, we re-allocate the array and lose the old one.
237240
size := runtime.GOMAXPROCS(0)
@@ -249,35 +252,47 @@ func poolCleanup() {
249252
// pinned section (in effect, this has all Ps pinned).
250253

251254
// Drop victim caches from all pools.
252-
for _, p := range oldPools {
253-
p.victim = nil
254-
p.victimSize = 0
255+
for i, s := range oldPools {
256+
for _, p := range s.s {
257+
p.victim = nil
258+
p.victimSize = 0
259+
}
260+
oldPools[i].s = nil
255261
}
256262

257263
// Move primary cache to victim cache.
258-
for _, p := range allPools {
259-
p.victim = p.local
260-
p.victimSize = p.localSize
261-
p.local = nil
262-
p.localSize = 0
264+
for i := range allPools {
265+
for _, p := range allPools[i].s {
266+
p.victim = p.local
267+
p.victimSize = p.localSize
268+
p.local = nil
269+
p.localSize = 0
270+
}
271+
oldPools[i].s = allPools[i].s
272+
allPools[i].s = nil
263273
}
264274

265275
// The pools with non-empty primary caches now have non-empty
266276
// victim caches and no pools have primary caches.
267-
oldPools, allPools = allPools, nil
268277
}
269278

270-
var (
271-
allPoolsMu Mutex
279+
const shardPoolsSize = 256
272280

281+
var (
273282
// allPools is the set of pools that have non-empty primary
274283
// caches. Protected by either 1) allPoolsMu and pinning or 2)
275284
// STW.
276-
allPools []*Pool
285+
allPools [shardPoolsSize]struct {
286+
lock Mutex
287+
s []*Pool
288+
_ [cpu.CacheLinePadSize - unsafe.Sizeof([]*Pool{}) - unsafe.Sizeof(Mutex{})]int8
289+
}
277290

278291
// oldPools is the set of pools that may have non-empty victim
279292
// caches. Protected by STW.
280-
oldPools []*Pool
293+
oldPools [shardPoolsSize]struct {
294+
s []*Pool
295+
}
281296
)
282297

283298
func init() {

0 commit comments

Comments
 (0)