Skip to content

Commit f5dea61

Browse files
committed
Improve workerJamDuration mechanism
1 parent 94ce7e4 commit f5dea61

File tree

2 files changed

+39
-2
lines changed

2 files changed

+39
-2
lines changed

worker/pool.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ type DefaultWorkerPool struct {
7777
jobQueue *fpgo.BufferedChannelQueue[func()]
7878

7979
workerCount int
80+
workerBusy int
8081
spawnWorkerCh fpgo.ChannelQueue[int]
8182
lastAliveTime time.Time
8283

@@ -122,6 +123,7 @@ func (workerPoolSelf *DefaultWorkerPool) trySpawn() {
122123
}
123124
// Avoid Jam if (now - lastAliveTime) is over workerJamDuration
124125
if time.Now().Sub(workerPoolSelf.lastAliveTime) > workerPoolSelf.workerJamDuration &&
126+
workerPoolSelf.workerBusy >= workerPoolSelf.workerCount &&
125127
workerPoolSelf.workerCount >= expectedWorkerCount {
126128
expectedWorkerCount = workerPoolSelf.workerCount + 1
127129
}
@@ -176,6 +178,7 @@ func (workerPoolSelf *DefaultWorkerPool) generateWorkerWithMaximum(maximum int)
176178
// workerID := time.Now()
177179
workerPoolSelf.lastAliveTime = time.Now()
178180
workerPoolSelf.workerCount++
181+
isBusy := false
179182

180183
go func() {
181184
// Recover & Recycle
@@ -188,6 +191,9 @@ func (workerPoolSelf *DefaultWorkerPool) generateWorkerWithMaximum(maximum int)
188191

189192
workerPoolSelf.lock.Lock()
190193
workerPoolSelf.workerCount--
194+
if isBusy {
195+
workerPoolSelf.workerBusy --
196+
}
191197
workerPoolSelf.lock.Unlock()
192198
}()
193199

@@ -203,7 +209,17 @@ func (workerPoolSelf *DefaultWorkerPool) generateWorkerWithMaximum(maximum int)
203209
select {
204210
case job := <-workerPoolSelf.jobQueue.GetChannel():
205211
if job != nil {
212+
workerPoolSelf.lock.Lock()
213+
isBusy = true
214+
workerPoolSelf.workerBusy ++
215+
workerPoolSelf.lock.Unlock()
216+
206217
job()
218+
219+
workerPoolSelf.lock.Lock()
220+
workerPoolSelf.workerBusy --
221+
isBusy = false
222+
workerPoolSelf.lock.Unlock()
207223
}
208224
case <-time.After(workerPoolSelf.workerExpiryDuration):
209225
workerPoolSelf.lock.RLock()

worker/pool_test.go

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,26 +114,47 @@ func TestWorkerJamDuration(t *testing.T) {
114114
v := i
115115
err = workerPool.Schedule(func() {
116116
// Nothing to do
117-
time.Sleep(10 * time.Millisecond)
117+
time.Sleep(20 * time.Millisecond)
118118
t.Log(v)
119119
anyOneDone = true
120120
})
121121
assert.NoError(t, err)
122122
}
123-
time.Sleep(1 * time.Millisecond)
123+
time.Sleep(3 * time.Millisecond)
124124
// BatchSize: 0, SetWorkerSizeStandBy: 3 -> 3 workers
125125
assert.Equal(t, 3, defaultWorkerPool.workerCount)
126126
time.Sleep(3 * time.Millisecond)
127+
// Though there're blocking jobs, but no newest job goes into the queue
128+
assert.Equal(t, 3, defaultWorkerPool.workerCount)
129+
// There're new jobs going to the queue, and all goroutines are busy
127130
workerPool.Schedule(func(){})
128131
workerPool.Schedule(func(){})
129132
workerPool.Schedule(func(){})
130133
time.Sleep(3 * time.Millisecond)
134+
// A new expected goroutine is generated
131135
assert.Equal(t, 4, defaultWorkerPool.workerCount)
136+
workerPool.Schedule(func(){})
137+
workerPool.Schedule(func(){})
138+
workerPool.Schedule(func(){})
139+
time.Sleep(3 * time.Millisecond)
140+
// Only non blocking jobs, thus keep the same amount
141+
assert.Equal(t, 4, defaultWorkerPool.workerCount)
142+
// There's a blocking jobs going to the queue
143+
workerPool.Schedule(func(){
144+
time.Sleep(20 * time.Millisecond)
145+
t.Log(3)
146+
anyOneDone = true
147+
})
148+
time.Sleep(3 * time.Millisecond)
149+
// Though there're blocking jobs, but no newest job goes into the queue
150+
assert.Equal(t, 4, defaultWorkerPool.workerCount)
151+
// There're new jobs going to the queue, and all goroutines are busy
132152
workerPool.Schedule(func(){})
133153
workerPool.Schedule(func(){})
134154
workerPool.Schedule(func(){})
135155
workerPool.Schedule(func(){})
136156
assert.Equal(t, false, anyOneDone)
137157
time.Sleep(1 * time.Millisecond)
158+
// A new expected goroutine is generated
138159
assert.Equal(t, 5, defaultWorkerPool.workerCount)
139160
}

0 commit comments

Comments
 (0)