Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

executor: add cache padding for lock of RowContainer #37627

Merged
merged 10 commits into from
Sep 7, 2022
21 changes: 14 additions & 7 deletions util/chunk/row_container.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/pingcap/tidb/util/logutil"
"github.com/pingcap/tidb/util/memory"
"go.uber.org/zap"
"golang.org/x/sys/cpu"
)

type rowContainerRecord struct {
Expand All @@ -36,6 +37,8 @@ type rowContainerRecord struct {
}

type mutexForRowContainer struct {
// Add cache padding to avoid false sharing issue.
_ cpu.CacheLinePad
// RWMutex guarantees spill and get operator for rowContainer is mutually exclusive.
// `rLock` and `wLocks` is introduced to reduce the contention when multiple
// goroutine touch the same rowContainer concurrently. If there are multiple
Expand All @@ -44,9 +47,10 @@ type mutexForRowContainer struct {
// each goroutine. Thus each goroutine holds its own rLock but share the same
// underlying data, which can reduce the contention on m.rLock remarkably and
// get better performance.
rLock *sync.RWMutex
rLock sync.RWMutex
wLocks []*sync.RWMutex
records *rowContainerRecord
_ cpu.CacheLinePad
}

// Lock locks rw for writing.
Expand Down Expand Up @@ -86,16 +90,16 @@ type RowContainer struct {
// NewRowContainer creates a new RowContainer in memory.
func NewRowContainer(fieldType []*types.FieldType, chunkSize int) *RowContainer {
li := NewList(fieldType, chunkSize, chunkSize)
rLock := new(sync.RWMutex)
rc := &RowContainer{
m: &mutexForRowContainer{
records: &rowContainerRecord{inMemory: li},
rLock: rLock,
wLocks: []*sync.RWMutex{rLock},
rLock: sync.RWMutex{},
wLocks: []*sync.RWMutex{},
},
memTracker: memory.NewTracker(memory.LabelForRowContainer, -1),
diskTracker: disk.NewTracker(memory.LabelForRowContainer, -1),
}
rc.m.wLocks = append(rc.m.wLocks, &rc.m.rLock)
li.GetMemTracker().AttachTo(rc.GetMemTracker())
return rc
}
Expand All @@ -105,9 +109,12 @@ func NewRowContainer(fieldType []*types.FieldType, chunkSize int) *RowContainer
// holds an individual rLock.
func (c *RowContainer) ShallowCopyWithNewMutex() *RowContainer {
newRC := *c
rLock := new(sync.RWMutex)
c.m.wLocks = append(c.m.wLocks, rLock)
newRC.m.rLock = rLock
newRC.m = &mutexForRowContainer{
records: c.m.records,
rLock: sync.RWMutex{},
wLocks: []*sync.RWMutex{},
}
c.m.wLocks = append(c.m.wLocks, &newRC.m.rLock)
return &newRC
}

Expand Down