Repository: valkey-io/valkey
File: src/expire.c (C)

Code before:
    serverDb *db;
    long long now;
    unsigned long sampled; /* num keys checked */
    unsigned long expired; /* num keys expired */
    long long ttl_sum;     /* sum of ttl for key with ttl not yet expired */
    int ttl_samples;       /* num keys with ttl not yet expired */
} expireScanData;

void expireScanCallback(void *privdata, void *entry) {
    robj *val = entry;
    expireScanData *data = privdata;
    long long ttl = objectGetExpire(val) - data->now;
    if (activeExpireCycleTryExpire(data->db, val, data->now)) {
        data->expired++;
        /* Propagate the DEL command */
        postExecutionUnitOperations();
    }
    if (ttl > 0) {
        /* We want the average TTL of keys yet not expired. */
        data->ttl_sum += ttl;
        data->ttl_samples++;
    }
    data->sampled++;
}

static inline int expiryTableShouldSkipForSamplingCb(hashtable *ht) {
    long long numkeys = hashtableSize(ht);
    unsigned long buckets = hashtableBuckets(ht);
    /* When there are less than 1% filled buckets, sampling the key
     * space is expensive, so stop here waiting for better times...
     * The dictionary will be resized asap. */
    if (buckets > 0 && (numkeys * 100 / buckets < 1)) {
        return 1;
    }
    return 0;
}

void activeExpireCycle(int type) {
    /* Adjust the running parameters according to the configured expire
     * effort. The default effort is 1, and the maximum configurable effort
     * is 10. */
    unsigned long effort = server.active_expire_effort - 1, /* Rescale from 0 to 9. */
        config_keys_per_loop = ACTIVE_EXPIRE_CYCLE_KEYS_PER_LOOP + ACTIVE_EXPIRE_CYCLE_KEYS_PER_LOOP / 4 * effort,
                  config_cycle_fast_duration =
                      ACTIVE_EXPIRE_CYCLE_FAST_DURATION + ACTIVE_EXPIRE_CYCLE_FAST_DURATION / 4 * effort,
                  config_cycle_slow_time_perc = ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC + 2 * effort,
                  config_cycle_acceptable_stale = ACTIVE_EXPIRE_CYCLE_ACCEPTABLE_STALE - effort;

    /* This function has some global state in order to continue the work
     * incrementally across calls. */
    static unsigned int current_db = 0;   /* Next DB to test. */

Review comment (suggestion):
Good, but maybe reorder the words for better grammar? "Should skip table for sampling" is better than "Table should skip for sampling" I think.

```suggestion
static inline int expiryShouldSkipTableForSamplingCb(hashtable *ht) {
```

Oh, is "expiry" the prefix for this file, or is "expiryTable" one concept? Maybe it should be one of these?

1. expireShouldSkipTableForSamplingCb (prefix "expire" like the filename)
2. shouldSkipExpiryTableForSamplingCb (if expiryTable is one concept)

Code after:
    serverDb *db;
    long long now;
    unsigned long sampled; /* num keys checked */
    unsigned long expired; /* num keys expired */
    long long ttl_sum;     /* sum of ttl for key with ttl not yet expired */
    int ttl_samples;       /* num keys with ttl not yet expired */
} expireScanData;

void expireScanCallback(void *privdata, void *entry) {
    robj *val = entry;
    expireScanData *data = privdata;
    long long ttl = objectGetExpire(val) - data->now;
    if (activeExpireCycleTryExpire(data->db, val, data->now)) {
        data->expired++;
        /* Propagate the DEL command */
        postExecutionUnitOperations();
    }
    if (ttl > 0) {
        /* We want the average TTL of keys yet not expired. */
        data->ttl_sum += ttl;
        data->ttl_samples++;
    }
    data->sampled++;
}

static inline int expireShouldSkipTableForSamplingCb(hashtable *ht) {
    long long numkeys = hashtableSize(ht);
    unsigned long buckets = hashtableBuckets(ht);
    /* When there are less than 1% filled buckets, sampling the key
     * space is expensive, so stop here waiting for better times...
     * The dictionary will be resized asap. */
    if (buckets > 0 && (numkeys * 100 / buckets < 1)) {
        return 1;
    }
    return 0;
}

void activeExpireCycle(int type) {
    /* Adjust the running parameters according to the configured expire
     * effort. The default effort is 1, and the maximum configurable effort
     * is 10. */
    unsigned long effort = server.active_expire_effort - 1, /* Rescale from 0 to 9. */
        config_keys_per_loop = ACTIVE_EXPIRE_CYCLE_KEYS_PER_LOOP + ACTIVE_EXPIRE_CYCLE_KEYS_PER_LOOP / 4 * effort,
                  config_cycle_fast_duration =
                      ACTIVE_EXPIRE_CYCLE_FAST_DURATION + ACTIVE_EXPIRE_CYCLE_FAST_DURATION / 4 * effort,
                  config_cycle_slow_time_perc = ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC + 2 * effort,
                  config_cycle_acceptable_stale = ACTIVE_EXPIRE_CYCLE_ACCEPTABLE_STALE - effort;

    /* This function has some global state in order to continue the work
     * incrementally across calls. */
    static unsigned int current_db = 0;   /* Next DB to test. */