summaryrefslogtreecommitdiff
path: root/src/setcpuaffinity.c
diff options
context:
space:
mode:
authorzhenwei pi <pizhenwei@bytedance.com>2020-05-02 20:05:39 +0800
committerzhenwei pi <pizhenwei@bytedance.com>2020-05-02 21:19:47 +0800
commit1a0deab2a548fa306171f03439e858c00836fe69 (patch)
tree776c4d73d8fa4f0e0dfa6f7c386327e9939186ea /src/setcpuaffinity.c
parent365316aa59545d90de4e105cec57f22aa5b52ff9 (diff)
downloadredis-1a0deab2a548fa306171f03439e858c00836fe69.tar.gz
Support setcpuaffinity on linux/bsd
Currently, there are several types of threads/child processes of a redis server. Sometimes we need deeply optimise the performance of redis, so we would like to isolate threads/processes. There were some discussion about cpu affinity cases in the issue: https://github.com/antirez/redis/issues/2863 So implement cpu affinity setting by redis.conf in this patch, then we can config server_cpulist/bio_cpulist/aof_rewrite_cpulist/ bgsave_cpulist by cpu list. Examples of cpulist in redis.conf: server_cpulist 0-7:2 means cpu affinity 0,2,4,6 bio_cpulist 1,3 means cpu affinity 1,3 aof_rewrite_cpulist 8-11 means cpu affinity 8,9,10,11 bgsave_cpulist 1,10-11 means cpu affinity 1,10,11 Test on linux/freebsd, both work fine. Signed-off-by: zhenwei pi <pizhenwei@bytedance.com>
Diffstat (limited to 'src/setcpuaffinity.c')
-rw-r--r--src/setcpuaffinity.c129
1 files changed, 129 insertions, 0 deletions
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 */