mirror of
https://github.com/minio/minio.git
synced 2025-11-07 12:52:58 -05:00
Optimize read locker cleanup (#14200)
When objects hold a lot of read locks cleanup time grows exponentially.
```
BEFORE:
Unable to complete tests.
AFTER:
=== RUN Test_localLocker_expireOldLocksExpire/100-locks/1-read
local-locker_test.go:298: Scan Took: 0s. Left: 100/100
local-locker_test.go:317: Expire 50% took: 0s. Left: 44/44
local-locker_test.go:331: Expire rest took: 0s. Left: 0/0
=== RUN Test_localLocker_expireOldLocksExpire/100-locks/100-read
local-locker_test.go:298: Scan Took: 0s. Left: 10000/100
local-locker_test.go:317: Expire 50% took: 1ms. Left: 5000/100
local-locker_test.go:331: Expire rest took: 1ms. Left: 0/0
=== RUN Test_localLocker_expireOldLocksExpire/100-locks/1000-read
local-locker_test.go:298: Scan Took: 2ms. Left: 100000/100
local-locker_test.go:317: Expire 50% took: 55ms. Left: 50038/100
local-locker_test.go:331: Expire rest took: 29ms. Left: 0/0
=== RUN Test_localLocker_expireOldLocksExpire/10000-locks/1-read
local-locker_test.go:298: Scan Took: 1ms. Left: 10000/10000
local-locker_test.go:317: Expire 50% took: 2ms. Left: 5019/5019
local-locker_test.go:331: Expire rest took: 2ms. Left: 0/0
=== RUN Test_localLocker_expireOldLocksExpire/10000-locks/100-read
local-locker_test.go:298: Scan Took: 23ms. Left: 1000000/10000
local-locker_test.go:317: Expire 50% took: 160ms. Left: 499798/10000
local-locker_test.go:331: Expire rest took: 138ms. Left: 0/0
=== RUN Test_localLocker_expireOldLocksExpire/10000-locks/1000-read
local-locker_test.go:298: Scan Took: 200ms. Left: 10000000/10000
local-locker_test.go:317: Expire 50% took: 5.888s. Left: 5000196/10000
local-locker_test.go:331: Expire rest took: 3.417s. Left: 0/0
=== RUN Test_localLocker_expireOldLocksExpire/1000000-locks/1-read
local-locker_test.go:298: Scan Took: 133ms. Left: 1000000/1000000
local-locker_test.go:317: Expire 50% took: 348ms. Left: 500255/500255
local-locker_test.go:331: Expire rest took: 307ms. Left: 0/0
```
This commit is contained in:
@@ -349,25 +349,29 @@ func (l *localLocker) expireOldLocks(interval time.Duration) {
|
||||
l.mutex.Lock()
|
||||
defer l.mutex.Unlock()
|
||||
|
||||
for k := range l.lockMap {
|
||||
found := false
|
||||
// Since we mutate the value, remove one per loop.
|
||||
for {
|
||||
lris, ok := l.lockMap[k]
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
for _, lri := range lris {
|
||||
if time.Since(lri.TimeLastRefresh) > interval {
|
||||
l.removeEntry(lri.Name, dsync.LockArgs{Owner: lri.Owner, UID: lri.UID}, &lris)
|
||||
found = true
|
||||
for k, lris := range l.lockMap {
|
||||
modified := false
|
||||
for i := 0; i < len(lris); {
|
||||
lri := &lris[i]
|
||||
if time.Since(lri.TimeLastRefresh) > interval {
|
||||
delete(l.lockUID, formatUUID(lri.UID, lri.idx))
|
||||
if len(lris) == 1 {
|
||||
// Remove the write lock.
|
||||
delete(l.lockMap, lri.Name)
|
||||
modified = false
|
||||
break
|
||||
}
|
||||
modified = true
|
||||
// Remove the appropriate lock.
|
||||
lris = append(lris[:i], lris[i+1:]...)
|
||||
// Check same i
|
||||
} else {
|
||||
// Move to next
|
||||
i++
|
||||
}
|
||||
// We did not find any more to expire.
|
||||
if !found {
|
||||
break
|
||||
}
|
||||
}
|
||||
if modified {
|
||||
l.lockMap[k] = lris
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user