diff --git a/src/config.c b/src/config.c index 54494c8e..5acea06d 100644 --- a/src/config.c +++ b/src/config.c @@ -441,9 +441,9 @@ void loadServerConfigFromString(char *config) { err = "argument must be 'yes' or 'no'"; goto loaderr; } } else if (!strcasecmp(argv[0],"hz") && argc == 2) { - server.hz = atoi(argv[1]); - if (server.hz < CONFIG_MIN_HZ) server.hz = CONFIG_MIN_HZ; - if (server.hz > CONFIG_MAX_HZ) server.hz = CONFIG_MAX_HZ; + server.config_hz = atoi(argv[1]); + if (server.config_hz < CONFIG_MIN_HZ) server.config_hz = CONFIG_MIN_HZ; + if (server.config_hz > CONFIG_MAX_HZ) server.config_hz = CONFIG_MAX_HZ; } else if (!strcasecmp(argv[0],"appendonly") && argc == 2) { int yes; @@ -1158,11 +1158,11 @@ void configSetCommand(client *c) { } config_set_numerical_field( "cluster-slave-validity-factor",server.cluster_slave_validity_factor,0,INT_MAX) { } config_set_numerical_field( - "hz",server.hz,0,INT_MAX) { + "hz",server.config_hz,0,INT_MAX) { /* Hz is more an hint from the user, so we accept values out of range * but cap them to reasonable values. */ - if (server.hz < CONFIG_MIN_HZ) server.hz = CONFIG_MIN_HZ; - if (server.hz > CONFIG_MAX_HZ) server.hz = CONFIG_MAX_HZ; + if (server.config_hz < CONFIG_MIN_HZ) server.config_hz = CONFIG_MIN_HZ; + if (server.config_hz > CONFIG_MAX_HZ) server.config_hz = CONFIG_MAX_HZ; } config_set_numerical_field( "watchdog-period",ll,0,INT_MAX) { if (ll) @@ -1329,7 +1329,7 @@ void configGetCommand(client *c) { config_get_numerical_field("slave-announce-port",server.slave_announce_port); config_get_numerical_field("min-slaves-to-write",server.repl_min_slaves_to_write); config_get_numerical_field("min-slaves-max-lag",server.repl_min_slaves_max_lag); - config_get_numerical_field("hz",server.hz); + config_get_numerical_field("hz",server.config_hz); config_get_numerical_field("cluster-node-timeout",server.cluster_node_timeout); config_get_numerical_field("cluster-migration-barrier",server.cluster_migration_barrier); config_get_numerical_field("cluster-slave-validity-factor",server.cluster_slave_validity_factor); @@ -2098,7 +2098,7 @@ int rewriteConfig(char *path) { rewriteConfigYesNoOption(state,"activedefrag",server.active_defrag_enabled,CONFIG_DEFAULT_ACTIVE_DEFRAG); rewriteConfigYesNoOption(state,"protected-mode",server.protected_mode,CONFIG_DEFAULT_PROTECTED_MODE); rewriteConfigClientoutputbufferlimitOption(state); - rewriteConfigNumericalOption(state,"hz",server.hz,CONFIG_DEFAULT_HZ); + rewriteConfigNumericalOption(state,"hz",server.config_hz,CONFIG_DEFAULT_HZ); rewriteConfigYesNoOption(state,"aof-rewrite-incremental-fsync",server.aof_rewrite_incremental_fsync,CONFIG_DEFAULT_AOF_REWRITE_INCREMENTAL_FSYNC); rewriteConfigYesNoOption(state,"rdb-save-incremental-fsync",server.rdb_save_incremental_fsync,CONFIG_DEFAULT_RDB_SAVE_INCREMENTAL_FSYNC); rewriteConfigYesNoOption(state,"aof-load-truncated",server.aof_load_truncated,CONFIG_DEFAULT_AOF_LOAD_TRUNCATED); diff --git a/src/server.c b/src/server.c index 8d168da3..965cae96 100644 --- a/src/server.c +++ b/src/server.c @@ -1096,6 +1096,17 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) { /* Update the time cache. */ updateCachedTime(); + /* Adapt the server.hz value to the number of configured clients. If we have + * many clients, we want to call serverCron() with an higher frequency. */ + server.hz = server.config_hz; + while (listLength(server.clients) / server.hz > MAX_CLIENTS_PER_CLOCK_TICK) { + server.hz *= 2; + if (server.hz > CONFIG_MAX_HZ) { + server.hz = CONFIG_MAX_HZ; + break; + } + } + run_with_period(100) { trackInstantaneousMetric(STATS_METRIC_COMMAND,server.stat_numcommands); trackInstantaneousMetric(STATS_METRIC_NET_INPUT, @@ -1512,7 +1523,7 @@ void initServerConfig(void) { server.timezone = timezone; /* Initialized by tzset(). */ server.configfile = NULL; server.executable = NULL; - server.hz = CONFIG_DEFAULT_HZ; + server.config_hz = CONFIG_DEFAULT_HZ; server.arch_bits = (sizeof(long) == 8) ? 64 : 32; server.port = CONFIG_DEFAULT_SERVER_PORT; server.tcp_backlog = CONFIG_DEFAULT_TCP_BACKLOG; @@ -1991,6 +2002,7 @@ void initServer(void) { server.syslog_facility); } + server.hz = server.config_hz; server.pid = getpid(); server.current_client = NULL; server.clients = listCreate(); @@ -3074,6 +3086,7 @@ sds genRedisInfoString(char *section) { "uptime_in_seconds:%jd\r\n" "uptime_in_days:%jd\r\n" "hz:%d\r\n" + "configured_hz:%d\r\n" "lru_clock:%ld\r\n" "executable:%s\r\n" "config_file:%s\r\n", @@ -3097,6 +3110,7 @@ sds genRedisInfoString(char *section) { (intmax_t)uptime, (intmax_t)(uptime/(3600*24)), server.hz, + server.config_hz, (unsigned long) lruclock, server.executable ? server.executable : "", server.configfile ? server.configfile : ""); diff --git a/src/server.h b/src/server.h index 14aed7fc..4d63faa6 100644 --- a/src/server.h +++ b/src/server.h @@ -78,12 +78,13 @@ typedef long long mstime_t; /* millisecond time type. */ #define C_ERR -1 /* Static server configuration */ -#define CONFIG_DEFAULT_HZ 10 /* Time interrupt calls/sec. */ +#define CONFIG_DEFAULT_HZ 10 /* Time interrupt calls/sec. */ #define CONFIG_MIN_HZ 1 #define CONFIG_MAX_HZ 500 -#define CONFIG_DEFAULT_SERVER_PORT 6379 /* TCP port */ -#define CONFIG_DEFAULT_TCP_BACKLOG 511 /* TCP listen backlog */ -#define CONFIG_DEFAULT_CLIENT_TIMEOUT 0 /* default client timeout: infinite */ +#define MAX_CLIENTS_PER_CLOCK_TICK 200 /* HZ is adapted based on that. */ +#define CONFIG_DEFAULT_SERVER_PORT 6379 /* TCP port. */ +#define CONFIG_DEFAULT_TCP_BACKLOG 511 /* TCP listen backlog. */ +#define CONFIG_DEFAULT_CLIENT_TIMEOUT 0 /* Default client timeout: infinite */ #define CONFIG_DEFAULT_DBNUM 16 #define CONFIG_MAX_LINE 1024 #define CRON_DBS_PER_CALL 16 @@ -91,7 +92,7 @@ typedef long long mstime_t; /* millisecond time type. */ #define PROTO_SHARED_SELECT_CMDS 10 #define OBJ_SHARED_INTEGERS 10000 #define OBJ_SHARED_BULKHDR_LEN 32 -#define LOG_MAX_LEN 1024 /* Default maximum length of syslog messages */ +#define LOG_MAX_LEN 1024 /* Default maximum length of syslog messages.*/ #define AOF_REWRITE_PERC 100 #define AOF_REWRITE_MIN_SIZE (64*1024*1024) #define AOF_REWRITE_ITEMS_PER_CMD 64 @@ -924,6 +925,9 @@ struct redisServer { char *configfile; /* Absolute config file path, or NULL */ char *executable; /* Absolute executable file path. */ char **exec_argv; /* Executable argv vector (copy). */ + int config_hz; /* Configured HZ value. May be different than + the actual 'hz' field value if dynamic-hz + is enabled. */ int hz; /* serverCron() calls frequency in hertz */ redisDb *db; dict *commands; /* Command table */