Skip to content
This repository has been archived by the owner on Sep 23, 2023. It is now read-only.

Commit

Permalink
leak detector
Browse files Browse the repository at this point in the history
  • Loading branch information
AskAlexSharov committed May 8, 2023
1 parent fe163c5 commit e79a7b8
Showing 1 changed file with 28 additions and 15 deletions.
43 changes: 28 additions & 15 deletions common/dbg/leak_detector.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,27 @@ import (
// periodically does print in logs resources which living longer than 1min with their creation stack trace
// For example db transactions can call Add/Del from Begin/Commit/Rollback methods
type LeakDetector struct {
enabled bool
list map[uint64]LeakDetectorItem
enabled atomic.Bool
slowThreshold atomic.Pointer[time.Duration]
autoIncrement atomic.Uint64
lock sync.Mutex

list map[uint64]LeakDetectorItem
listLock sync.Mutex
}

type LeakDetectorItem struct {
stack string
started time.Time
}

func NewLeakDetector(name string, enabled bool) *LeakDetector {
func NewLeakDetector(name string, slowThreshold time.Duration) *LeakDetector {
enabled := slowThreshold > 0
if !enabled {
return nil
}
d := &LeakDetector{enabled: enabled, list: map[uint64]LeakDetectorItem{}}
d := &LeakDetector{list: map[uint64]LeakDetectorItem{}}
d.SetSlowThreshold(slowThreshold)

if enabled {
go func() {
logEvery := time.NewTicker(60 * time.Second)
Expand All @@ -49,15 +54,17 @@ func NewLeakDetector(name string, enabled bool) *LeakDetector {
}

func (d *LeakDetector) slowList() (res []string) {
if d == nil || !d.enabled {
if d == nil || !d.Enabled() {
return res
}
d.lock.Lock()
defer d.lock.Unlock()
slowThreshold := *d.slowThreshold.Load()

d.listLock.Lock()
defer d.listLock.Unlock()
i := 0
for key, value := range d.list {
living := time.Since(value.started)
if living > time.Minute {
if living > slowThreshold {
res = append(res, fmt.Sprintf("%d(%s): %s", key, living, value.stack))
}
i++
Expand All @@ -69,24 +76,30 @@ func (d *LeakDetector) slowList() (res []string) {
}

func (d *LeakDetector) Del(id uint64) {
if d == nil || !d.enabled {
if d == nil || !d.Enabled() {
return
}
d.lock.Lock()
defer d.lock.Unlock()
d.listLock.Lock()
defer d.listLock.Unlock()
delete(d.list, id)
}
func (d *LeakDetector) Add() uint64 {
if d == nil || !d.enabled {
if d == nil || !d.Enabled() {
return 0
}
ac := LeakDetectorItem{
stack: StackSkip(2),
started: time.Now(),
}
id := d.autoIncrement.Add(1)
d.lock.Lock()
defer d.lock.Unlock()
d.listLock.Lock()
defer d.listLock.Unlock()
d.list[id] = ac
return id
}

func (d *LeakDetector) Enabled() bool { return d.enabled.Load() }
func (d *LeakDetector) SetSlowThreshold(t time.Duration) {
d.slowThreshold.Store(&t)
d.enabled.Store(t > 0)
}

0 comments on commit e79a7b8

Please sign in to comment.