Skip to content

Commit 2988527

Browse files
committed
purge
1 parent 92df7d8 commit 2988527

3 files changed

Lines changed: 62 additions & 2 deletions

File tree

FUTURE.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
* [x] 支持设置 worker 任务队列大小
1313
* [x] 支持设置 panic 处理函数
1414
* [x] 支持自定义 sync.Locker 实现
15+
* [ ] 增加 worker 内存复用池
16+
* [ ] 增加 workers 切片内存复用池
1517
* [x] 完善单元测试,将覆盖率提高到 95% 以上
1618

1719
### v0.1.0

config.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import (
1414
type config struct {
1515
workerNum int
1616
workerQueueSize int
17+
workerLifetime time.Duration
18+
purgeInterval time.Duration
1719
nowFunc func() time.Time
1820
recoverFunc func(r any)
1921
newLockerFunc func() sync.Locker
@@ -24,6 +26,8 @@ func newDefaultConfig(workerNum int) *config {
2426
return &config{
2527
workerNum: workerNum,
2628
workerQueueSize: 64,
29+
workerLifetime: 0,
30+
purgeInterval: 0,
2731
nowFunc: nil,
2832
recoverFunc: nil,
2933
newLockerFunc: nil,

executor.go

Lines changed: 56 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package goes
77
import (
88
"errors"
99
"sync"
10+
"time"
1011
)
1112

1213
var (
@@ -24,6 +25,7 @@ type Executor struct {
2425

2526
workers []*worker
2627
scheduler scheduler
28+
closeCh chan struct{}
2729
closed bool
2830

2931
wg sync.WaitGroup
@@ -50,11 +52,13 @@ func NewExecutor(workerNum int, opts ...Option) *Executor {
5052
conf: conf,
5153
workers: workers,
5254
scheduler: conf.newScheduler(),
55+
closeCh: make(chan struct{}, 1),
5356
closed: false,
5457
lock: conf.newLocker(),
5558
}
5659

5760
executor.spawnWorker()
61+
executor.runPurgeTask()
5862
return executor
5963
}
6064

@@ -66,6 +70,54 @@ func (e *Executor) spawnWorker() *worker {
6670
return worker
6771
}
6872

73+
func (e *Executor) purgeActive() bool {
74+
return e.conf.purgeInterval > 0 && e.conf.workerLifetime > 0
75+
}
76+
77+
func (e *Executor) purgeWorkers() {
78+
e.lock.Lock()
79+
defer e.lock.Unlock()
80+
81+
now := e.conf.now()
82+
oldWorkers := e.workers
83+
newWorkers := make([]*worker, 0, len(oldWorkers))
84+
for _, worker := range oldWorkers {
85+
if worker.WaitingTasks() <= 0 && now.Sub(worker.AcceptTime()) >= e.conf.workerLifetime {
86+
worker.Done()
87+
} else {
88+
newWorkers = append(newWorkers, worker)
89+
}
90+
}
91+
92+
e.workers = newWorkers
93+
e.scheduler.Set(e.workers)
94+
95+
// Avoid gc leaks.
96+
for i := range oldWorkers {
97+
oldWorkers[i] = nil
98+
}
99+
}
100+
101+
func (e *Executor) runPurgeTask() {
102+
if !e.purgeActive() {
103+
return
104+
}
105+
106+
go func() {
107+
ticker := time.NewTicker(e.conf.purgeInterval)
108+
defer ticker.Stop()
109+
110+
for {
111+
select {
112+
case <-ticker.C:
113+
e.purgeWorkers()
114+
case <-e.closeCh:
115+
return
116+
}
117+
}
118+
}()
119+
}
120+
69121
// AvailableWorkers returns the number of workers available.
70122
func (e *Executor) AvailableWorkers() int {
71123
e.lock.Lock()
@@ -97,9 +149,11 @@ func (e *Executor) Submit(task Task) error {
97149
worker = e.spawnWorker()
98150
}
99151

100-
worker.SetAcceptTime(e.conf.now())
101-
e.lock.Unlock()
152+
if e.purgeActive() {
153+
worker.SetAcceptTime(e.conf.now())
154+
}
102155

156+
e.lock.Unlock()
103157
worker.Accept(task)
104158
return nil
105159
}

0 commit comments

Comments
 (0)