Update PR #6537 patch to for generality.

After the thread in #6537 and thanks to the suggestions received, this
commit updates the original patch in order to:

1. Solve the problem of updating the time in multiple places by updating
it in call().
2. Avoid introducing a new field but use our cached time.

This required some minor refactoring to the function updating the time,
and the introduction of a new cached time in microseconds in order to
use less gettimeofday() calls.
This commit is contained in:
antirez 2019-11-05 10:14:34 +01:00
parent e542132b07
commit 824f5f0b7a
4 changed files with 34 additions and 19 deletions

View File

@ -1198,8 +1198,12 @@ int keyIsExpired(redisDb *db, robj *key) {
* blocked to when the Lua script started. This way a key can expire * blocked to when the Lua script started. This way a key can expire
* only the first time it is accessed and not in the middle of the * only the first time it is accessed and not in the middle of the
* script execution, making propagation to slaves / AOF consistent. * script execution, making propagation to slaves / AOF consistent.
* See issue #1525 on Github for more information. */ * See issue #1525 on Github for more information.
mstime_t now = server.lua_caller ? server.lua_time_start : server.cmd_start_mstime; *
* Outside the Lua script execution, we use the cached time server.mstime
* that is updated before commands executions in call(). */
mstime_t now = server.lua_caller ? server.lua_time_start :
server.mstime;
return now > when; return now > when;
} }

View File

@ -1961,7 +1961,7 @@ void rdbLoadProgressCallback(rio *r, const void *buf, size_t len) {
/* The DB can take some non trivial amount of time to load. Update /* The DB can take some non trivial amount of time to load. Update
* our cached time since it is used to create and update the last * our cached time since it is used to create and update the last
* interaction time with clients and for other important things. */ * interaction time with clients and for other important things. */
updateCachedTime(); updateCachedTime(0);
if (server.masterhost && server.repl_state == REPL_STATE_TRANSFER) if (server.masterhost && server.repl_state == REPL_STATE_TRANSFER)
replicationSendNewlineToMaster(); replicationSendNewlineToMaster();
loadingProgress(r->processed_bytes); loadingProgress(r->processed_bytes);

View File

@ -1736,20 +1736,29 @@ void databasesCron(void) {
/* We take a cached value of the unix time in the global state because with /* We take a cached value of the unix time in the global state because with
* virtual memory and aging there is to store the current time in objects at * virtual memory and aging there is to store the current time in objects at
* every object access, and accuracy is not needed. To access a global var is * every object access, and accuracy is not needed. To access a global var is
* a lot faster than calling time(NULL) */ * a lot faster than calling time(NULL).
void updateCachedTime(void) { *
server.unixtime = time(NULL); * This function should be fast because it is called at every command execution
server.mstime = mstime(); * in call(), so it is possible to decide if to update the daylight saving
* info or not using the 'update_daylight_info' argument. Normally we update
* such info only when calling this function from serverCron() but not when
* calling it from call(). */
void updateCachedTime(int update_daylight_info) {
server.ustime = ustime();
server.mstime = server.ustime / 1000;
server.unixtime = server.mstime / 1000;
/* To get information about daylight saving time, we need to call /* To get information about daylight saving time, we need to call
* localtime_r and cache the result. However calling localtime_r in this * localtime_r and cache the result. However calling localtime_r in this
* context is safe since we will never fork() while here, in the main * context is safe since we will never fork() while here, in the main
* thread. The logging function will call a thread safe version of * thread. The logging function will call a thread safe version of
* localtime that has no locks. */ * localtime that has no locks. */
if (update_daylight_info) {
struct tm tm; struct tm tm;
time_t ut = server.unixtime; time_t ut = server.unixtime;
localtime_r(&ut,&tm); localtime_r(&ut,&tm);
server.daylight_active = tm.tm_isdst; server.daylight_active = tm.tm_isdst;
}
} }
void checkChildrenDone(void) { void checkChildrenDone(void) {
@ -1838,7 +1847,7 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
if (server.watchdog_period) watchdogScheduleSignal(server.watchdog_period); if (server.watchdog_period) watchdogScheduleSignal(server.watchdog_period);
/* Update the time cache. */ /* Update the time cache. */
updateCachedTime(); updateCachedTime(1);
server.hz = server.config_hz; server.hz = server.config_hz;
/* Adapt the server.hz value to the number of configured clients. If we have /* Adapt the server.hz value to the number of configured clients. If we have
@ -2252,7 +2261,7 @@ void createSharedObjects(void) {
void initServerConfig(void) { void initServerConfig(void) {
int j; int j;
updateCachedTime(); updateCachedTime(1);
getRandomHexChars(server.runid,CONFIG_RUN_ID_SIZE); getRandomHexChars(server.runid,CONFIG_RUN_ID_SIZE);
server.runid[CONFIG_RUN_ID_SIZE] = '\0'; server.runid[CONFIG_RUN_ID_SIZE] = '\0';
changeReplicationId(); changeReplicationId();
@ -3238,7 +3247,8 @@ void preventCommandReplication(client *c) {
* *
*/ */
void call(client *c, int flags) { void call(client *c, int flags) {
long long dirty, start, duration; long long dirty;
ustime_t start, duration;
int client_old_flags = c->flags; int client_old_flags = c->flags;
struct redisCommand *real_cmd = c->cmd; struct redisCommand *real_cmd = c->cmd;
@ -3259,7 +3269,8 @@ void call(client *c, int flags) {
/* Call the command. */ /* Call the command. */
dirty = server.dirty; dirty = server.dirty;
start = ustime(); updateCachedTime(0);
start = server.ustime;
c->cmd->proc(c); c->cmd->proc(c);
duration = ustime()-start; duration = ustime()-start;
dirty = server.dirty-dirty; dirty = server.dirty-dirty;
@ -3596,7 +3607,6 @@ int processCommand(client *c) {
queueMultiCommand(c); queueMultiCommand(c);
addReply(c,shared.queued); addReply(c,shared.queued);
} else { } else {
server.cmd_start_mstime = mstime();
call(c,CMD_CALL_FULL); call(c,CMD_CALL_FULL);
c->woff = server.master_repl_offset; c->woff = server.master_repl_offset;
if (listLength(server.ready_keys)) if (listLength(server.ready_keys))

View File

@ -50,6 +50,7 @@
#include <signal.h> #include <signal.h>
typedef long long mstime_t; /* millisecond time type. */ typedef long long mstime_t; /* millisecond time type. */
typedef long long ustime_t; /* microsecond time type. */
#include "ae.h" /* Event driven programming library */ #include "ae.h" /* Event driven programming library */
#include "sds.h" /* Dynamic safe strings */ #include "sds.h" /* Dynamic safe strings */
@ -1400,8 +1401,8 @@ struct redisServer {
_Atomic time_t unixtime; /* Unix time sampled every cron cycle. */ _Atomic time_t unixtime; /* Unix time sampled every cron cycle. */
time_t timezone; /* Cached timezone. As set by tzset(). */ time_t timezone; /* Cached timezone. As set by tzset(). */
int daylight_active; /* Currently in daylight saving time. */ int daylight_active; /* Currently in daylight saving time. */
long long mstime; /* 'unixtime' with milliseconds resolution. */ mstime_t mstime; /* 'unixtime' in milliseconds. */
mstime_t cmd_start_mstime; ustime_t ustime; /* 'unixtime' in microseconds. */
/* Pubsub */ /* Pubsub */
dict *pubsub_channels; /* Map channels to list of subscribed clients */ dict *pubsub_channels; /* Map channels to list of subscribed clients */
list *pubsub_patterns; /* A list of pubsub_patterns */ list *pubsub_patterns; /* A list of pubsub_patterns */
@ -1997,7 +1998,7 @@ void populateCommandTable(void);
void resetCommandTableStats(void); void resetCommandTableStats(void);
void adjustOpenFilesLimit(void); void adjustOpenFilesLimit(void);
void closeListeningSockets(int unlink_unix_socket); void closeListeningSockets(int unlink_unix_socket);
void updateCachedTime(void); void updateCachedTime(int update_daylight_info);
void resetServerStats(void); void resetServerStats(void);
void activeDefragCycle(void); void activeDefragCycle(void);
unsigned int getLRUClock(void); unsigned int getLRUClock(void);