Skip to content

Commit

Permalink
Optimize the memory usage of LockManager Locked queue and wait queue
Browse files Browse the repository at this point in the history
  • Loading branch information
snower committed May 21, 2024
1 parent 8d4f469 commit 92470f3
Show file tree
Hide file tree
Showing 7 changed files with 363 additions and 51 deletions.
9 changes: 4 additions & 5 deletions server/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -619,8 +619,8 @@ func (self *Admin) commandHandleShowLockCommand(serverProtocol *TextServerProtoc
}

if lockManager.locks != nil {
for i := range lockManager.locks.IterNodes() {
nodeQueues := lockManager.locks.IterNodeQueues(int32(i))
for i := range lockManager.locks.queue.IterNodes() {
nodeQueues := lockManager.locks.queue.IterNodeQueues(int32(i))
for _, lock := range nodeQueues {
if lock.locked == 0 {
continue
Expand Down Expand Up @@ -670,9 +670,8 @@ func (self *Admin) commandHandleShowLockWaitCommand(serverProtocol *TextServerPr
lockInfos := make([]string, 0)
lockManager.glock.LowPriorityLock()
if lockManager.waitLocks != nil {
for i := range lockManager.waitLocks.IterNodes() {
nodeQueues := lockManager.waitLocks.IterNodeQueues(int32(i))
for _, lock := range nodeQueues {
for _, waitLocks := range lockManager.waitLocks.IterNodes() {
for _, lock := range waitLocks {
if lock.timeouted {
continue
}
Expand Down
14 changes: 4 additions & 10 deletions server/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -1015,7 +1015,6 @@ func (self *LockDB) initNewLockManager(dbId uint8) {
lockManagers[i].lockDb = self
lockManagers[i].dbId = dbId
lockManagers[i].locks = nil
lockManagers[i].lockMaps = nil
lockManagers[i].waitLocks = nil
lockManagers[i].glock = self.managerGlocks[self.managerGlockIndex]
lockManagers[i].glockIndex = self.managerGlockIndex
Expand Down Expand Up @@ -1134,9 +1133,8 @@ func (self *LockDB) RemoveLockManager(lockManager *LockManager) {
self.freeLockManagers[freeLockManagerHead] = lockManager

lockManager.locks = nil
lockManager.lockMaps = nil
if lockManager.waitLocks != nil {
_ = lockManager.waitLocks.Rellac()
lockManager.waitLocks.Rellac()
}
lockManager.currentData = nil
atomic.AddUint32(&lockManager.state.KeyCount, 0xffffffff)
Expand All @@ -1148,7 +1146,6 @@ func (self *LockDB) RemoveLockManager(lockManager *LockManager) {
lockManager.currentLock = nil
lockManager.currentData = nil
lockManager.locks = nil
lockManager.lockMaps = nil
lockManager.waitLocks = nil
lockManager.freeLocks = nil
atomic.AddUint32(&lockManager.state.KeyCount, 0xffffffff)
Expand Down Expand Up @@ -1176,9 +1173,8 @@ func (self *LockDB) RemoveLockManager(lockManager *LockManager) {
self.freeLockManagers[freeLockManagerHead] = lockManager

lockManager.locks = nil
lockManager.lockMaps = nil
if lockManager.waitLocks != nil {
_ = lockManager.waitLocks.Rellac()
lockManager.waitLocks.Rellac()
}
lockManager.currentData = nil
atomic.AddUint32(&lockManager.state.KeyCount, 0xffffffff)
Expand All @@ -1190,7 +1186,6 @@ func (self *LockDB) RemoveLockManager(lockManager *LockManager) {
lockManager.currentLock = nil
lockManager.currentData = nil
lockManager.locks = nil
lockManager.lockMaps = nil
lockManager.waitLocks = nil
lockManager.freeLocks = nil
atomic.AddUint32(&lockManager.state.KeyCount, 0xffffffff)
Expand Down Expand Up @@ -2189,9 +2184,8 @@ func (self *LockDB) wakeUpWaitLock(lockManager *LockManager, waitLock *Lock, ser
func (self *LockDB) cancelWaitLock(lockManager *LockManager, command *protocol.LockCommand, serverProtocol ServerProtocol) {
var waitLock *Lock = nil
if lockManager.waitLocks != nil {
for i := range lockManager.waitLocks.IterNodes() {
nodeQueues := lockManager.waitLocks.IterNodeQueues(int32(i))
for _, lock := range nodeQueues {
for _, waitLocks := range lockManager.waitLocks.IterNodes() {
for _, lock := range waitLocks {
if lock.timeouted {
continue
}
Expand Down
177 changes: 152 additions & 25 deletions server/lock.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,151 @@ import (
"sync/atomic"
)

type LockManagerRingQueue struct {
queue []*Lock
index int
}

func NewLockManagerRingQueue(size int) *LockManagerRingQueue {
return &LockManagerRingQueue{make([]*Lock, 0, size), 0}
}

func (self *LockManagerRingQueue) Push(lock *Lock) {
if len(self.queue) == cap(self.queue) {
if self.index > len(self.queue)/2 {
copy(self.queue, self.queue[self.index:])
self.queue = self.queue[:len(self.queue)-self.index]
self.index = 0
}
}
self.queue = append(self.queue, lock)
}

func (self *LockManagerRingQueue) Pop() *Lock {
if self.index >= len(self.queue) {
return nil
}
lock := self.queue[self.index]
self.queue[self.index] = nil
self.index++
if self.index >= len(self.queue) {
self.queue = self.queue[:0]
self.index = 0
}
return lock
}

func (self *LockManagerRingQueue) Head() *Lock {
if self.index >= len(self.queue) {
return nil
}
return self.queue[self.index]
}

type LockManagerLockQueue struct {
queue *LockQueue
maps map[[16]byte]*Lock
}

func NewLockManagerLockQueue() *LockManagerLockQueue {
return &LockManagerLockQueue{NewLockQueue(4, 16, 4), make(map[[16]byte]*Lock)}
}

func (self *LockManagerLockQueue) Push(lock *Lock) {
err := self.queue.Push(lock)
if err == nil {
self.maps[lock.command.LockId] = lock
}
}

func (self *LockManagerLockQueue) Pop() *Lock {
return self.queue.Pop()
}

func (self *LockManagerLockQueue) Head() *Lock {
return self.queue.Head()
}

type LockManagerWaitQueue struct {
fastQueue []*Lock
fastIndex int
ringQueue *LockManagerRingQueue
}

func NewLockManagerWaitQueue() *LockManagerWaitQueue {
return &LockManagerWaitQueue{make([]*Lock, 0, 16), 0, nil}
}

func (self *LockManagerWaitQueue) Push(lock *Lock) {
if self.ringQueue != nil {
self.ringQueue.Push(lock)
return
}
if len(self.fastQueue) == cap(self.fastQueue) {
if self.fastIndex > len(self.fastQueue)/2 {
copy(self.fastQueue, self.fastQueue[self.fastIndex:])
self.fastQueue = self.fastQueue[:len(self.fastQueue)-self.fastIndex]
self.fastIndex = 0
} else {
self.ringQueue = NewLockManagerRingQueue(64)
self.ringQueue.Push(lock)
return
}
}
self.fastQueue = append(self.fastQueue, lock)
}

func (self *LockManagerWaitQueue) Pop() *Lock {
if self.fastIndex < len(self.fastQueue) {
lock := self.fastQueue[self.fastIndex]
self.fastQueue[self.fastIndex] = nil
self.fastIndex++
if self.fastIndex >= len(self.fastQueue) {
self.fastQueue = self.fastQueue[:0]
self.fastIndex = 0
}
return lock
}
if self.ringQueue != nil {
return self.ringQueue.Pop()
}
return nil
}

func (self *LockManagerWaitQueue) Head() *Lock {
if self.fastIndex < len(self.fastQueue) {
return self.fastQueue[self.fastIndex]
}
if self.ringQueue != nil {
return self.ringQueue.Head()
}
return nil
}

func (self *LockManagerWaitQueue) Rellac() {
self.fastQueue = self.fastQueue[:0]
self.fastIndex = 0
self.ringQueue = nil
}

func (self *LockManagerWaitQueue) IterNodes() [][]*Lock {
lockNodes := make([][]*Lock, 0, 2)
if self.fastIndex < len(self.fastQueue) {
lockNodes = append(lockNodes, self.fastQueue[self.fastIndex:])
}
if self.ringQueue != nil && self.ringQueue.index < len(self.ringQueue.queue) {
lockNodes = append(lockNodes, self.ringQueue.queue[self.ringQueue.index:])
}
return lockNodes
}

type LockManager struct {
lockDb *LockDB
lockKey [16]byte
currentLock *Lock
currentData *LockManagerData
locks *LockQueue
lockMaps map[[16]byte]*Lock
waitLocks *LockQueue
locks *LockManagerLockQueue
waitLocks *LockManagerWaitQueue
glock *PriorityMutex
freeLocks *LockQueue
fastKeyValue *FastKeyValue
Expand All @@ -27,7 +164,7 @@ type LockManager struct {

func NewLockManager(lockDb *LockDB, command *protocol.LockCommand, glock *PriorityMutex, glockIndex uint16, freeLocks *LockQueue, state *protocol.LockDBState) *LockManager {
return &LockManager{lockDb, command.LockKey, nil, nil, nil, nil,
nil, glock, freeLocks, nil, state, 0, 0,
glock, freeLocks, nil, state, 0, 0,
glockIndex, command.DbId, false}
}

Expand Down Expand Up @@ -86,11 +223,9 @@ func (self *LockManager) AddLock(lock *Lock) *Lock {
self.currentLock = lock
} else {
if self.locks == nil {
self.locks = NewLockQueue(4, 4, 4)
self.lockMaps = make(map[[16]byte]*Lock, 8)
self.locks = NewLockManagerLockQueue()
}
_ = self.locks.Push(lock)
self.lockMaps[lock.command.LockId] = lock
self.locks.Push(lock)
}
return lock
}
Expand All @@ -109,7 +244,7 @@ func (self *LockManager) RemoveLock(lock *Lock) *Lock {
lockedLock := self.locks.Pop()
for lockedLock != nil {
if lockedLock.locked > 0 {
delete(self.lockMaps, lockedLock.command.LockId)
delete(self.locks.maps, lockedLock.command.LockId)
self.currentLock = lockedLock
break
}
Expand All @@ -121,16 +256,16 @@ func (self *LockManager) RemoveLock(lock *Lock) *Lock {
lockedLock = self.locks.Pop()
}

if self.locks.headNodeIndex >= 8 {
_ = self.locks.Resize()
if self.locks.queue.headNodeIndex >= 8 {
_ = self.locks.queue.Resize()
}
return lock
}

if self.locks == nil {
return lock
}
delete(self.lockMaps, lock.command.LockId)
delete(self.locks.maps, lock.command.LockId)
lockedLock := self.locks.Head()
for lockedLock != nil {
if lockedLock.locked > 0 {
Expand All @@ -145,8 +280,8 @@ func (self *LockManager) RemoveLock(lock *Lock) *Lock {
lockedLock = self.locks.Head()
}

if self.locks.headNodeIndex >= 8 {
_ = self.locks.Resize()
if self.locks.queue.headNodeIndex >= 8 {
_ = self.locks.queue.Resize()
}
return lock
}
Expand All @@ -158,7 +293,7 @@ func (self *LockManager) GetLockedLock(command *protocol.LockCommand) *Lock {
if self.locks == nil {
return nil
}
lockedLock, ok := self.lockMaps[command.LockId]
lockedLock, ok := self.locks.maps[command.LockId]
if ok {
return lockedLock
}
Expand Down Expand Up @@ -246,9 +381,9 @@ func (self *LockManager) UpdateLockedLock(lock *Lock, command *protocol.LockComm

func (self *LockManager) AddWaitLock(lock *Lock) *Lock {
if self.waitLocks == nil {
self.waitLocks = NewLockQueue(4, 4, 4)
self.waitLocks = NewLockManagerWaitQueue()
}
_ = self.waitLocks.Push(lock)
self.waitLocks.Push(lock)
lock.refCount++
self.waited = true
return lock
Expand All @@ -269,16 +404,8 @@ func (self *LockManager) GetWaitLock() *Lock {
lock = self.waitLocks.Head()
continue
}

if self.waitLocks.headNodeIndex >= 8 {
_ = self.waitLocks.Resize()
}
return lock
}

if self.waitLocks.headNodeIndex >= 8 {
_ = self.waitLocks.Resize()
}
return nil
}

Expand Down
Loading

0 comments on commit 92470f3

Please sign in to comment.