Skip to content

Commit 8930ec9

Browse files
authored
Merge pull request #183 from deploymenttheory/dev
Adjust response time variability threshold and concurrency logic in t…
2 parents b6f800b + 3d8b531 commit 8930ec9

File tree

2 files changed

+32
-18
lines changed

2 files changed

+32
-18
lines changed

concurrency/const.go

+5
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,9 @@ const (
5454
// high. If response times exceed this threshold, it could signal that the system or the external service
5555
// is under heavy load and may benefit from scaling down concurrency to alleviate pressure.
5656
ResponseTimeCriticalThreshold = 2 * time.Second
57+
58+
debounceScaleDownThreshold = 5 // Number of consecutive triggers before scaling down
59+
60+
//
61+
AcceptableAverageResponseTime = 100 * time.Millisecond
5762
)

concurrency/metrics.go

+27-18
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"math"
66
"net/http"
77
"strconv"
8+
"sync"
89
"time"
910

1011
"go.uber.org/zap"
@@ -194,39 +195,47 @@ func (ch *ConcurrencyHandler) MonitorServerResponseCodes(resp *http.Response) in
194195

195196
// A slice to hold the last n response times for averaging
196197
var responseTimes []time.Duration
198+
var responseTimesLock sync.Mutex
197199

200+
// MonitorResponseTimeVariability monitors the response time variability and suggests a concurrency adjustment.
198201
// MonitorResponseTimeVariability monitors the response time variability and suggests a concurrency adjustment.
199202
func (ch *ConcurrencyHandler) MonitorResponseTimeVariability(responseTime time.Duration) int {
200-
ch.Metrics.Lock.Lock() // Ensure thread safety when accessing shared metrics
201-
defer ch.Metrics.Lock.Unlock()
203+
ch.Metrics.ResponseTimeVariability.Lock.Lock()
204+
defer ch.Metrics.ResponseTimeVariability.Lock.Unlock()
202205

203-
// Append the latest response time
206+
responseTimesLock.Lock() // Ensure safe concurrent access
204207
responseTimes = append(responseTimes, responseTime)
205-
if len(responseTimes) > 10 { // Use the last 10 measurements for a smoother average
206-
responseTimes = responseTimes[1:]
208+
if len(responseTimes) > 10 {
209+
responseTimes = responseTimes[1:] // Maintain last 10 measurements
207210
}
211+
responseTimesLock.Unlock()
208212

209213
stdDev := calculateStdDev(responseTimes)
214+
averageResponseTime := calculateAverage(responseTimes)
210215

211-
// Action determination with debounce effect
212-
// Debounce mechanism for scaling down
213-
const debounceCount = 3 // Threshold must be exceeded in 3 consecutive checks to act
214-
if stdDev > (ch.Metrics.ResponseTimeVariability.StdDevThreshold * 2) {
216+
// Multi-factor check before scaling down
217+
if stdDev > ch.Metrics.ResponseTimeVariability.StdDevThreshold && averageResponseTime > AcceptableAverageResponseTime {
215218
ch.Metrics.ResponseTimeVariability.DebounceScaleDownCount++
216-
ch.logger.Info("Increased debounce counter", zap.Int("counter", ch.Metrics.ResponseTimeVariability.DebounceScaleDownCount))
217-
if ch.Metrics.ResponseTimeVariability.DebounceScaleDownCount >= debounceCount {
218-
ch.Metrics.ResponseTimeVariability.DebounceScaleDownCount = 0 // reset counter after action
219-
ch.logger.Info("Concurrent requests scaling down due to high response time variability")
219+
if ch.Metrics.ResponseTimeVariability.DebounceScaleDownCount >= debounceScaleDownThreshold {
220+
ch.Metrics.ResponseTimeVariability.DebounceScaleDownCount = 0
220221
return -1 // Suggest decrease concurrency
221222
}
222223
} else {
223-
ch.Metrics.ResponseTimeVariability.DebounceScaleDownCount = 0 // reset counter if condition not met
224-
if stdDev <= ch.Metrics.ResponseTimeVariability.StdDevThreshold && len(ch.sem) < cap(ch.sem) {
225-
ch.logger.Info("Concurrent requests scaling up as conditions are favorable")
226-
return 1 // Suggest increase concurrency if there is capacity
224+
ch.Metrics.ResponseTimeVariability.DebounceScaleDownCount = 0 // Reset counter if conditions are not met
225+
if stdDev <= ch.Metrics.ResponseTimeVariability.StdDevThreshold {
226+
return 1 // Suggest increase concurrency if conditions are favorable
227227
}
228228
}
229-
return 0
229+
return 0 // Default to no change
230+
}
231+
232+
// calculateAverage computes the average response time from a slice of response times.
233+
func calculateAverage(times []time.Duration) time.Duration {
234+
var total time.Duration
235+
for _, t := range times {
236+
total += t
237+
}
238+
return total / time.Duration(len(times))
230239
}
231240

232241
// calculateStdDev computes the standard deviation of response times.

0 commit comments

Comments
 (0)