Commit a8a981a8 authored by antirez's avatar antirez
Browse files

Impovements for: Redis timer, hashes rehashing, keys collection.

A previous commit introduced REDIS_HZ define that changes the frequency
of calls to the serverCron() Redis function. This commit improves
different related things:

1) Software watchdog: now the minimal period can be set according to
REDIS_HZ. The minimal period is two times the timer period, that is:

    (1000/REDIS_HZ)*2 milliseconds

2) The incremental rehashing is now performed in the expires dictionary
as well.

3) The activeExpireCycle() function was improved in different ways:

- Now it checks if it already used too much time using microseconds
  instead of milliseconds for better precision.
- The time limit is now calculated correctly, in the previous version
  the division was performed before of the multiplication resulting in
  a timelimit of 0 if HZ was big enough.
- Databases with less than 1% of buckets fill in the hash table are
  skipped, because getting random keys is too expensive in this
  condition.

4) tryResizeHashTabl...
parent f7f2b261
......@@ -722,6 +722,8 @@ void watchdogScheduleSignal(int period) {
/* Enable the software watchdong with the specified period in milliseconds. */
void enableWatchdog(int period) {
int min_period;
if (server.watchdog_period == 0) {
struct sigaction act;
......@@ -732,7 +734,11 @@ void enableWatchdog(int period) {
act.sa_sigaction = watchdogSignalHandler;
sigaction(SIGALRM, &act, NULL);
}
if (period < 200) period = 200; /* We don't accept periods < 200 ms. */
/* If the configured period is smaller than twice the timer period, it is
* too short for the software watchdog to work reliably. Fix it now
* if needed. */
min_period = (1000/REDIS_HZ)*2;
if (period < min_period) period = min_period;
watchdogScheduleSignal(period); /* Adjust the current timer. */
server.watchdog_period = period;
}
......
......@@ -581,10 +581,16 @@ void incrementallyRehash(void) {
int j;
for (j = 0; j < server.dbnum; j++) {
/* Keys dictionary */
if (dictIsRehashing(server.db[j].dict)) {
dictRehashMilliseconds(server.db[j].dict,1);
break; /* already used our millisecond for this loop... */
}
/* Expires */
if (dictIsRehashing(server.db[j].expires)) {
dictRehashMilliseconds(server.db[j].expires,1);
break; /* already used our millisecond for this loop... */
}
}
}
......@@ -609,13 +615,13 @@ void updateDictResizePolicy(void) {
* keys that can be removed from the keyspace. */
void activeExpireCycle(void) {
int j;
long long start = mstime(), timelimit;
long long start = ustime(), timelimit;
/* We can use at max REDIS_EXPIRELOOKUPS_TIME_PERC percentage of CPU time
* per iteration. Since this function gets called with a frequency of
* REDIS_HZ times per second, the following is the max amount of
* milliseconds we can spend here: */
timelimit = (1000/REDIS_HZ/100)*REDIS_EXPIRELOOKUPS_TIME_PERC;
* microseconds we can spend in this function. */
timelimit = 1000000*REDIS_EXPIRELOOKUPS_TIME_PERC/REDIS_HZ/100;
if (timelimit <= 0) timelimit = 1;
for (j = 0; j < server.dbnum; j++) {
......@@ -625,9 +631,16 @@ void activeExpireCycle(void) {
/* Continue to expire if at the end of the cycle more than 25%
* of the keys were expired. */
do {
long num = dictSize(db->expires);
unsigned long num = dictSize(db->expires);
unsigned long slots = dictSlots(db->expires);
long long now = mstime();
/* When there are less than 1% filled slots getting random
* keys is expensive, so stop here waiting for better times...
* The dictionary will be resized asap. */
if (num && slots > DICT_HT_INITIAL_SIZE &&
(num*100/slots < 1)) break;
expired = 0;
if (num > REDIS_EXPIRELOOKUPS_PER_CRON)
num = REDIS_EXPIRELOOKUPS_PER_CRON;
......@@ -653,7 +666,7 @@ void activeExpireCycle(void) {
* caller waiting for the other active expire cycle. */
iteration++;
if ((iteration & 0xff) == 0 && /* Check once every 255 iterations */
(mstime()-start) > timelimit) return;
(ustime()-start) > timelimit) return;
} while (expired > REDIS_EXPIRELOOKUPS_PER_CRON/4);
}
}
......@@ -856,7 +869,7 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
* a lot of memory movements in the parent will cause a lot of pages
* copied. */
if (server.rdb_child_pid == -1 && server.aof_child_pid == -1) {
run_with_period(1000) tryResizeHashTables();
tryResizeHashTables();
if (server.activerehashing) incrementallyRehash();
}
......
......@@ -38,7 +38,7 @@
#define REDIS_ERR -1
/* Static server configuration */
#define REDIS_HZ 10 /* Time interrupt calls/sec. */
#define REDIS_HZ 100 /* Time interrupt calls/sec. */
#define REDIS_SERVERPORT 6379 /* TCP port */
#define REDIS_MAXIDLETIME 0 /* default client timeout: infinite */
#define REDIS_DEFAULT_DBNUM 16
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment