@@ -18,16 +18,15 @@ const maxPathPartChars = 50
1818const maxRequestDrainage = 100
1919
2020var (
21- // TODO: test with different values
2221 // requests taking longer than this are considered slow (var for tests)
23- slowRequestThreshold = 1500 * time .Millisecond
24- // % of initial threads that are marked as low latency threads(var for tests)
25- lowLatencyPercentile = 25
22+ slowRequestThreshold = 2000 * time .Millisecond
23+ // % of autoscaled threads that are marked as low latency threads(var for tests)
24+ lowLatencyPercentile = 20
2625
26+ slowRequestPaths map [string ]time.Duration
2727 latencyTrackingEnabled = false
2828 latencyTrackingActive = atomic.Bool {}
2929 slowRequestsMu = sync.RWMutex {}
30- slowRequestPaths map [string ]time.Duration
3130 numRe = regexp .MustCompile (`^\d+$` )
3231 uuidRe = regexp .MustCompile (`^[a-f0-9-]{36}$` )
3332)
@@ -83,6 +82,7 @@ func trackRequestLatency(fc *frankenPHPContext, duration time.Duration, forceTra
8382 if recordedLatency == 0 && latencyTrackingActive .Load () {
8483 // a new path that is known to be slow is recorded,
8584 // drain some requests to free up low-latency threads
85+ // TODO: make sure this overhead is acceptable
8686 out:
8787 for i := 0 ; i < maxRequestDrainage ; i ++ {
8888 select {
@@ -96,17 +96,18 @@ func trackRequestLatency(fc *frankenPHPContext, duration time.Duration, forceTra
9696 }
9797 }
9898
99- // record the latency as a moving average
100- slowRequestPaths [normalizedPath ] = duration / 2 + recordedLatency / 2
99+ movingAverage := duration / 2 + recordedLatency / 2
100+ slowRequestPaths [normalizedPath ] = movingAverage
101101
102102 // remove the path if it is no longer considered slow
103- if forceTracking && slowRequestPaths [ normalizedPath ] < slowRequestThreshold {
103+ if forceTracking && movingAverage < slowRequestThreshold {
104104 delete (slowRequestPaths , normalizedPath )
105105 }
106+
106107 slowRequestsMu .Unlock ()
107108}
108109
109- // determine if a request is likely to be high latency based on the request path
110+ // determine if a request is likely to be high latency based on previous requests with the same path
110111func isHighLatencyRequest (fc * frankenPHPContext ) bool {
111112 if len (slowRequestPaths ) == 0 {
112113 return false
@@ -123,6 +124,11 @@ func isHighLatencyRequest(fc *frankenPHPContext) bool {
123124 return ! fc .isLowLatencyRequest
124125}
125126
127+ // normalize a path by replacing variable parts with wildcards
128+ // e.g. /user/123/profile -> /user/:id/profile
129+ //
130+ // /post/550e8400-e29b-41d4-a716-446655440000 -> /post/:uuid
131+ // /category/very-long-category-name -> /category/:slug
126132func normalizePath (path string ) string {
127133 pathLen := len (path )
128134 if pathLen > 1 && path [pathLen - 1 ] == '/' {
0 commit comments