summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSalvatore Sanfilippo <antirez@gmail.com>2020-05-04 10:56:20 +0200
committerGitHub <noreply@github.com>2020-05-04 10:56:20 +0200
commitacf566b29132e8353ac3592b9f908d1858594ead (patch)
tree5d91c60d6e6bb39716420dd06fc7d94b08f0c968
parent68ad748e77e11f774c4e95f4d6ab7713712cd77c (diff)
parent1a0deab2a548fa306171f03439e858c00836fe69 (diff)
downloadredis-acf566b29132e8353ac3592b9f908d1858594ead.tar.gz
Merge pull request #7179 from bytedance/cpu-affinity
Support setcpuaffinity on linux/bsd
-rw-r--r--redis.conf15
-rw-r--r--src/Makefile2
-rw-r--r--src/aof.c1
-rw-r--r--src/bio.c2
-rw-r--r--src/config.c4
-rw-r--r--src/config.h6
-rw-r--r--src/networking.c1
-rw-r--r--src/rdb.c2
-rw-r--r--src/server.c9
-rw-r--r--src/server.h6
-rw-r--r--src/setcpuaffinity.c129
-rw-r--r--tests/unit/introspection.tcl4
12 files changed, 180 insertions, 1 deletions
diff --git a/redis.conf b/redis.conf
index d96d26e1c..756073a27 100644
--- a/redis.conf
+++ b/redis.conf
@@ -1780,3 +1780,18 @@ rdb-save-incremental-fsync yes
# Maximum number of set/hash/zset/list fields that will be processed from
# the main dictionary scan
# active-defrag-max-scan-fields 1000
+
+# Redis server/IO threads, bio threads, aof rewrite child process, and bgsave
+# child process cpu affinity list config. syntax of cpu list looks like taskset
+# command. serveral examples:
+# set redis server/io threads to cpu affinity 0,2,4,6
+# server_cpulist 0-7:2
+#
+# set bio threads to cpu affinity 1,3
+# bio_cpulist 1,3
+#
+# set aof rewrite child process to cpu affinity 8,9,10,11
+# aof_rewrite_cpulist 8-11
+#
+# set bgsave child process to cpu affinity 1,10,11
+# bgsave_cpulist 1,10-11
diff --git a/src/Makefile b/src/Makefile
index f9922afce..55f862cfc 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -206,7 +206,7 @@ endif
REDIS_SERVER_NAME=redis-server
REDIS_SENTINEL_NAME=redis-sentinel
-REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crcspeed.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o redis-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o lolwut.o lolwut5.o lolwut6.o acl.o gopher.o tracking.o connection.o tls.o sha256.o timeout.o
+REDIS_SERVER_OBJ=adlist.o quicklist.o ae.o anet.o dict.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crcspeed.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o redis-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o lolwut.o lolwut5.o lolwut6.o acl.o gopher.o tracking.o connection.o tls.o sha256.o timeout.o setcpuaffinity.o
REDIS_CLI_NAME=redis-cli
REDIS_CLI_OBJ=anet.o adlist.o dict.o redis-cli.o zmalloc.o release.o ae.o crcspeed.o crc64.o siphash.o crc16.o
REDIS_BENCHMARK_NAME=redis-benchmark
diff --git a/src/aof.c b/src/aof.c
index 301a40848..02409abe6 100644
--- a/src/aof.c
+++ b/src/aof.c
@@ -1596,6 +1596,7 @@ int rewriteAppendOnlyFileBackground(void) {
/* Child */
redisSetProcTitle("redis-aof-rewrite");
+ redisSetCpuAffinity(server.aof_rewrite_cpulist);
snprintf(tmpfile,256,"temp-rewriteaof-bg-%d.aof", (int) getpid());
if (rewriteAppendOnlyFile(tmpfile) == C_OK) {
sendChildCOWInfo(CHILD_INFO_TYPE_AOF, "AOF rewrite");
diff --git a/src/bio.c b/src/bio.c
index 85f681185..69c62fc6f 100644
--- a/src/bio.c
+++ b/src/bio.c
@@ -166,6 +166,8 @@ void *bioProcessBackgroundJobs(void *arg) {
break;
}
+ redisSetCpuAffinity(server.bio_cpulist);
+
/* Make the thread killable at any time, so that bioKillThreads()
* can work reliably. */
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
diff --git a/src/config.c b/src/config.c
index e0cbcc281..64854592c 100644
--- a/src/config.c
+++ b/src/config.c
@@ -2133,6 +2133,10 @@ standardConfig configs[] = {
createStringConfig("syslog-ident", NULL, IMMUTABLE_CONFIG, ALLOW_EMPTY_STRING, server.syslog_ident, "redis", NULL, NULL),
createStringConfig("dbfilename", NULL, MODIFIABLE_CONFIG, ALLOW_EMPTY_STRING, server.rdb_filename, "dump.rdb", isValidDBfilename, NULL),
createStringConfig("appendfilename", NULL, IMMUTABLE_CONFIG, ALLOW_EMPTY_STRING, server.aof_filename, "appendonly.aof", isValidAOFfilename, NULL),
+ createStringConfig("server_cpulist", NULL, IMMUTABLE_CONFIG, EMPTY_STRING_IS_NULL, server.server_cpulist, NULL, NULL, NULL),
+ createStringConfig("bio_cpulist", NULL, IMMUTABLE_CONFIG, EMPTY_STRING_IS_NULL, server.bio_cpulist, NULL, NULL, NULL),
+ createStringConfig("aof_rewrite_cpulist", NULL, IMMUTABLE_CONFIG, EMPTY_STRING_IS_NULL, server.aof_rewrite_cpulist, NULL, NULL, NULL),
+ createStringConfig("bgsave_cpulist", NULL, IMMUTABLE_CONFIG, EMPTY_STRING_IS_NULL, server.bgsave_cpulist, NULL, NULL, NULL),
/* Enum Configs */
createEnumConfig("supervised", NULL, IMMUTABLE_CONFIG, supervised_mode_enum, server.supervised_mode, SUPERVISED_NONE, NULL, NULL),
diff --git a/src/config.h b/src/config.h
index 40dc683ce..a322ce354 100644
--- a/src/config.h
+++ b/src/config.h
@@ -244,4 +244,10 @@ int pthread_setname_np(const char *name);
#endif
#endif
+/* Check if we can use setcpuaffinity(). */
+#if (defined __linux || defined __NetBSD__ || defined __FreeBSD__ || defined __OpenBSD__)
+#define USE_SETCPUAFFINITY
+void setcpuaffinity(const char *cpulist);
+#endif
+
#endif
diff --git a/src/networking.c b/src/networking.c
index d62533e3e..fd1159e06 100644
--- a/src/networking.c
+++ b/src/networking.c
@@ -2872,6 +2872,7 @@ void *IOThreadMain(void *myid) {
snprintf(thdname, sizeof(thdname), "io_thd_%ld", id);
redis_set_thread_title(thdname);
+ redisSetCpuAffinity(server.server_cpulist);
while(1) {
/* Wait for start */
diff --git a/src/rdb.c b/src/rdb.c
index 7ac2d43c2..72ed23137 100644
--- a/src/rdb.c
+++ b/src/rdb.c
@@ -1351,6 +1351,7 @@ int rdbSaveBackground(char *filename, rdbSaveInfo *rsi) {
/* Child */
redisSetProcTitle("redis-rdb-bgsave");
+ redisSetCpuAffinity(server.bgsave_cpulist);
retval = rdbSave(filename,rsi);
if (retval == C_OK) {
sendChildCOWInfo(CHILD_INFO_TYPE_RDB, "RDB");
@@ -2486,6 +2487,7 @@ int rdbSaveToSlavesSockets(rdbSaveInfo *rsi) {
rioInitWithFd(&rdb,server.rdb_pipe_write);
redisSetProcTitle("redis-rdb-to-slaves");
+ redisSetCpuAffinity(server.bgsave_cpulist);
retval = rdbSaveRioWithEOFMark(&rdb,NULL,rsi);
if (retval == C_OK && rioFlush(&rdb) == 0)
diff --git a/src/server.c b/src/server.c
index 659604ef3..1baa044be 100644
--- a/src/server.c
+++ b/src/server.c
@@ -4850,6 +4850,14 @@ void redisSetProcTitle(char *title) {
#endif
}
+void redisSetCpuAffinity(const char *cpulist) {
+#ifdef USE_SETCPUAFFINITY
+ setcpuaffinity(cpulist);
+#else
+ UNUSED(cpulist);
+#endif
+}
+
/*
* Check whether systemd or upstart have been used to start redis.
*/
@@ -5118,6 +5126,7 @@ int main(int argc, char **argv) {
serverLog(LL_WARNING,"WARNING: You specified a maxmemory value that is less than 1MB (current value is %llu bytes). Are you sure this is what you really want?", server.maxmemory);
}
+ redisSetCpuAffinity(server.server_cpulist);
aeSetBeforeSleepProc(server.el,beforeSleep);
aeSetAfterSleepProc(server.el,afterSleep);
aeMain(server.el);
diff --git a/src/server.h b/src/server.h
index 41d767e13..af435b148 100644
--- a/src/server.h
+++ b/src/server.h
@@ -1433,6 +1433,11 @@ struct redisServer {
int tls_replication;
int tls_auth_clients;
redisTLSContextConfig tls_ctx_config;
+ /* cpu affinity */
+ char *server_cpulist; /* cpu affinity list of redis server main/io thread. */
+ char *bio_cpulist; /* cpu affinity list of bio thread. */
+ char *aof_rewrite_cpulist; /* cpu affinity list of aof rewrite process. */
+ char *bgsave_cpulist; /* cpu affinity list of bgsave process. */
};
typedef struct pubsubPattern {
@@ -1585,6 +1590,7 @@ void exitFromChild(int retcode);
size_t redisPopcount(void *s, long count);
void redisSetProcTitle(char *title);
int redisCommunicateSystemd(const char *sd_notify_msg);
+void redisSetCpuAffinity(const char *cpulist);
/* networking.c -- Networking and Client related operations */
client *createClient(connection *conn);
diff --git a/src/setcpuaffinity.c b/src/setcpuaffinity.c
new file mode 100644
index 000000000..1a12795cd
--- /dev/null
+++ b/src/setcpuaffinity.c
@@ -0,0 +1,129 @@
+/* ==========================================================================
+ * setproctitle.c - Linux/BSD setcpuaffinity.
+ * --------------------------------------------------------------------------
+ * Copyright (C) 2020 zhenwei pi
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to permit
+ * persons to whom the Software is furnished to do so, subject to the
+ * following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+ * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * ==========================================================================
+ */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#ifdef __linux__
+#include <sched.h>
+#endif
+#ifdef __FreeBSD__
+#include <sys/param.h>
+#include <sys/cpuset.h>
+#endif
+#include "config.h"
+
+#ifdef USE_SETCPUAFFINITY
+static const char *next_token(const char *q, int sep) {
+ if (q)
+ q = strchr(q, sep);
+ if (q)
+ q++;
+
+ return q;
+}
+
+static int next_num(const char *str, char **end, int *result) {
+ if (!str || *str == '\0' || !isdigit(*str))
+ return -1;
+
+ *result = strtoul(str, end, 10);
+ if (str == *end)
+ return -1;
+
+ return 0;
+}
+
+/* set current thread cpu affinity to cpu list, this function works like
+ * taskset command (actually cpulist parsing logic reference to util-linux).
+ * example of this function: "0,2,3", "0,2-3", "0-20:2". */
+void setcpuaffinity(const char *cpulist) {
+ const char *p, *q;
+ char *end = NULL;
+#ifdef __linux__
+ cpu_set_t cpuset;
+#endif
+#ifdef __FreeBSD__
+ cpuset_t cpuset;
+#endif
+
+ if (!cpulist)
+ return;
+
+ CPU_ZERO(&cpuset);
+
+ q = cpulist;
+ while (p = q, q = next_token(q, ','), p) {
+ int a, b, s;
+ const char *c1, *c2;
+
+ if (next_num(p, &end, &a) != 0)
+ return;
+
+ b = a;
+ s = 1;
+ p = end;
+
+ c1 = next_token(p, '-');
+ c2 = next_token(p, ',');
+
+ if (c1 != NULL && (c2 == NULL || c1 < c2)) {
+ if (next_num(c1, &end, &b) != 0)
+ return;
+
+ c1 = end && *end ? next_token(end, ':') : NULL;
+ if (c1 != NULL && (c2 == NULL || c1 < c2)) {
+ if (next_num(c1, &end, &s) != 0)
+ return;
+
+ if (s == 0)
+ return;
+ }
+ }
+
+ if ((a > b))
+ return;
+
+ while (a <= b) {
+ CPU_SET(a, &cpuset);
+ a += s;
+ }
+ }
+
+ if (end && *end)
+ return;
+
+#ifdef __linux__
+ sched_setaffinity(0, sizeof(cpuset), &cpuset);
+#endif
+#ifdef __FreeBSD__
+ cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_TID, -1, sizeof(cpuset), &cpuset);
+#endif
+}
+
+#endif /* USE_SETCPUAFFINITY */
diff --git a/tests/unit/introspection.tcl b/tests/unit/introspection.tcl
index cd905084a..b60ca0d48 100644
--- a/tests/unit/introspection.tcl
+++ b/tests/unit/introspection.tcl
@@ -94,6 +94,10 @@ start_server {tags {"introspection"}} {
slaveof
bind
requirepass
+ server_cpulist
+ bio_cpulist
+ aof_rewrite_cpulist
+ bgsave_cpulist
}
set configs {}