Skip to content

Commit

Permalink
sync: optimize pinslow
Browse files Browse the repository at this point in the history
Change-Id: I0e12abb9bc848f6cb053f7b3d39beec65dadd967
  • Loading branch information
qiulaidongfeng committed Feb 7, 2024
1 parent 47dd861 commit 760ce2c
Showing 1 changed file with 31 additions and 16 deletions.
47 changes: 31 additions & 16 deletions src/sync/pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
package sync

import (
"internal/cpu"
"internal/race"
"runtime"
"sync/atomic"
Expand Down Expand Up @@ -76,6 +77,7 @@ type poolLocal struct {
}

// from runtime
//
//go:linkname runtime_randn runtime.randn
func runtime_randn(n uint32) uint32

Expand Down Expand Up @@ -221,8 +223,9 @@ func (p *Pool) pinSlow() (*poolLocal, int) {
// Retry under the mutex.
// Can not lock the mutex while pinned.
runtime_procUnpin()
allPoolsMu.Lock()
defer allPoolsMu.Unlock()
a := &allPools[uintptr(unsafe.Pointer(p))%shardPoolsSize]
a.lock.Lock()
defer a.lock.Unlock()
pid := runtime_procPin()
// poolCleanup won't be called while we are pinned.
s := p.localSize
Expand All @@ -231,7 +234,7 @@ func (p *Pool) pinSlow() (*poolLocal, int) {
return indexLocal(l, pid), pid
}
if p.local == nil {
allPools = append(allPools, p)
a.s = append(a.s, p)
}
// If GOMAXPROCS changes between GCs, we re-allocate the array and lose the old one.
size := runtime.GOMAXPROCS(0)
Expand All @@ -249,35 +252,47 @@ func poolCleanup() {
// pinned section (in effect, this has all Ps pinned).

// Drop victim caches from all pools.
for _, p := range oldPools {
p.victim = nil
p.victimSize = 0
for i, s := range oldPools {
for _, p := range s.s {
p.victim = nil
p.victimSize = 0
}
oldPools[i].s = nil
}

// Move primary cache to victim cache.
for _, p := range allPools {
p.victim = p.local
p.victimSize = p.localSize
p.local = nil
p.localSize = 0
for i := range allPools {
for _, p := range allPools[i].s {
p.victim = p.local
p.victimSize = p.localSize
p.local = nil
p.localSize = 0
}
oldPools[i].s = allPools[i].s
allPools[i].s = nil
}

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

var (
allPoolsMu Mutex
const shardPoolsSize = 256

var (
// allPools is the set of pools that have non-empty primary
// caches. Protected by either 1) allPoolsMu and pinning or 2)
// STW.
allPools []*Pool
allPools [shardPoolsSize]struct {
lock Mutex
s []*Pool
_ [cpu.CacheLinePadSize - unsafe.Sizeof([]*Pool{}) - unsafe.Sizeof(Mutex{})]int8
}

// oldPools is the set of pools that may have non-empty victim
// caches. Protected by STW.
oldPools []*Pool
oldPools [shardPoolsSize]struct {
s []*Pool
}
)

func init() {
Expand Down

0 comments on commit 760ce2c

Please sign in to comment.