@@ -111,9 +111,11 @@ int activeExpireCycleTryExpire(redisDb *db, dictEntry *de, long long now) {
111111 * little memory.
112112 */
113113
114- #define ACTIVE_EXPIRE_CYCLE_BUCKETS_PER_LOOP 20 /* HT buckets checked . */
114+ #define ACTIVE_EXPIRE_CYCLE_KEYS_PER_LOOP 20 /* Keys for each DB loop . */
115115#define ACTIVE_EXPIRE_CYCLE_FAST_DURATION 1000 /* Microseconds. */
116- #define ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC 25 /* Percentage of CPU to use. */
116+ #define ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC 25 /* Max % of CPU to use. */
117+ #define ACTIVE_EXPIRE_CYCLE_ACCEPTABLE_STALE 10 /* % of stale keys after which
118+ we do extra efforts. */
117119
118120void activeExpireCycle (int type ) {
119121 /* This function has some global state in order to continue the work
@@ -133,10 +135,15 @@ void activeExpireCycle(int type) {
133135
134136 if (type == ACTIVE_EXPIRE_CYCLE_FAST ) {
135137 /* Don't start a fast cycle if the previous cycle did not exit
136- * for time limit. Also don't repeat a fast cycle for the same period
138+ * for time limit, unless the percentage of estimated stale keys is
139+ * too high. Also never repeat a fast cycle for the same period
137140 * as the fast cycle total duration itself. */
138- if (!timelimit_exit ) return ;
139- if (start < last_fast_cycle + ACTIVE_EXPIRE_CYCLE_FAST_DURATION * 2 ) return ;
141+ if (!timelimit_exit && server .stat_expired_stale_perc <
142+ ACTIVE_EXPIRE_CYCLE_ACCEPTABLE_STALE ) return ;
143+
144+ if (start < last_fast_cycle + ACTIVE_EXPIRE_CYCLE_FAST_DURATION * 2 )
145+ return ;
146+
140147 last_fast_cycle = start ;
141148 }
142149
@@ -150,8 +157,8 @@ void activeExpireCycle(int type) {
150157 if (dbs_per_call > server .dbnum || timelimit_exit )
151158 dbs_per_call = server .dbnum ;
152159
153- /* We can use at max ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC percentage of CPU time
154- * per iteration. Since this function gets called with a frequency of
160+ /* We can use at max ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC percentage of CPU
161+ * time per iteration. Since this function gets called with a frequency of
155162 * server.hz times per second, the following is the max amount of
156163 * microseconds we can spend in this function. */
157164 timelimit = 1000000 * ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC /server .hz /100 ;
@@ -207,8 +214,8 @@ void activeExpireCycle(int type) {
207214 ttl_sum = 0 ;
208215 ttl_samples = 0 ;
209216
210- if (num > ACTIVE_EXPIRE_CYCLE_BUCKETS_PER_LOOP )
211- num = ACTIVE_EXPIRE_CYCLE_BUCKETS_PER_LOOP ;
217+ if (num > ACTIVE_EXPIRE_CYCLE_KEYS_PER_LOOP )
218+ num = ACTIVE_EXPIRE_CYCLE_KEYS_PER_LOOP ;
212219
213220 /* Here we access the low level representation of the hash table
214221 * for speed concerns: this makes this code coupled with dict.c,
@@ -268,9 +275,9 @@ void activeExpireCycle(int type) {
268275 }
269276 }
270277 /* We don't repeat the cycle for the current database if there are
271- * less than 25% of keys found expired in the current DB. */
272- // printf("[%d] Expired %d, sampled %d\n", type, (int) expired, (int) sampled);
273- } while (expired > sampled / 4 );
278+ * an acceptable amount of stale keys (logically expired but yet
279+ * not reclained). */
280+ } while (( expired * 100 / sampled ) > ACTIVE_EXPIRE_CYCLE_ACCEPTABLE_STALE );
274281 }
275282
276283 elapsed = ustime ()- start ;
0 commit comments