summary refs log tree commit diff
path: root/synapse
diff options
context:
space:
mode:
authorRichard van der Hoff <richard@matrix.org>2017-08-15 17:08:28 +0100
committerRichard van der Hoff <richard@matrix.org>2017-08-15 17:08:28 +0100
commit10d8b701a1fa585c5fc2d5edcea8d4d02ae360a4 (patch)
tree5c6a455a53db8c5eb91c8b648d0eb92daf05098e /synapse
parentFactor out common application start (diff)
downloadsynapse-10d8b701a1fa585c5fc2d5edcea8d4d02ae360a4.tar.xz
Allow configuration of CPU affinity
Make it possible to set the CPU affinity in the config file, so that we don't
need to remember to do it manually every time.
Diffstat (limited to 'synapse')
-rw-r--r--synapse/app/_base.py9
-rwxr-xr-xsynapse/app/homeserver.py1
-rw-r--r--synapse/config/server.py12
-rw-r--r--synapse/config/workers.py1
-rw-r--r--synapse/python_dependencies.py1
5 files changed, 23 insertions, 1 deletions
diff --git a/synapse/app/_base.py b/synapse/app/_base.py
index 3889c35946..cd0e815919 100644
--- a/synapse/app/_base.py
+++ b/synapse/app/_base.py
@@ -15,6 +15,7 @@
 import gc
 import logging
 
+import affinity
 from daemonize import Daemonize
 from synapse.util import PreserveLoggingContext
 from synapse.util.rlimit import change_resource_limit
@@ -40,7 +41,8 @@ def start_worker_reactor(appname, config):
         config.gc_thresholds,
         config.worker_pid_file,
         config.worker_daemonize,
-        logger
+        config.worker_cpu_affinity,
+        logger,
     )
 
 
@@ -50,6 +52,7 @@ def start_reactor(
         gc_thresholds,
         pid_file,
         daemonize,
+        cpu_affinity,
         logger,
 ):
     """ Run the reactor in the main process
@@ -63,6 +66,7 @@ def start_reactor(
         gc_thresholds:
         pid_file (str): name of pid file to write to if daemonize is True
         daemonize (bool): true to run the reactor in a background process
+        cpu_affinity (int|None): cpu affinity mask
         logger (logging.Logger): logger instance to pass to Daemonize
     """
 
@@ -73,6 +77,9 @@ def start_reactor(
         # between the sentinel and `run` logcontexts.
         with PreserveLoggingContext():
             logger.info("Running")
+            if cpu_affinity is not None:
+                logger.info("Setting CPU affinity to %s" % cpu_affinity)
+                affinity.set_process_affinity_mask(0, cpu_affinity)
             change_resource_limit(soft_file_limit)
             if gc_thresholds:
                 gc.set_threshold(*gc_thresholds)
diff --git a/synapse/app/homeserver.py b/synapse/app/homeserver.py
index 83b6c3212b..84ad8f04a0 100755
--- a/synapse/app/homeserver.py
+++ b/synapse/app/homeserver.py
@@ -442,6 +442,7 @@ def run(hs):
         hs.config.gc_thresholds,
         hs.config.pid_file,
         hs.config.daemonize,
+        hs.config.cpu_affinity,
         logger,
     )
 
diff --git a/synapse/config/server.py b/synapse/config/server.py
index 28b4e5f50c..4e4bf6b432 100644
--- a/synapse/config/server.py
+++ b/synapse/config/server.py
@@ -29,6 +29,7 @@ class ServerConfig(Config):
         self.user_agent_suffix = config.get("user_agent_suffix")
         self.use_frozen_dicts = config.get("use_frozen_dicts", False)
         self.public_baseurl = config.get("public_baseurl")
+        self.cpu_affinity = config.get("cpu_affinity")
 
         # Whether to send federation traffic out in this process. This only
         # applies to some federation traffic, and so shouldn't be used to
@@ -147,6 +148,17 @@ class ServerConfig(Config):
         # When running as a daemon, the file to store the pid in
         pid_file: %(pid_file)s
 
+        # CPU affinity mask. Setting this restricts the CPUs on which the process
+        # will be scheduled. It is represented as a bitmask, with the lowest order
+        # bit corresponding to the first logical CPU and the highest order bit
+        # corresponding to the last logical CPU. Not all CPUs may exist on a
+        # given system but a mask may specify more CPUs than are present.
+        # For example:
+        #    0x00000001  is processor #0,
+        #    0x00000003  is processors #0 and #1,
+        #    0xFFFFFFFF  is all processors (#0 through #31).
+        # cpu_affinity: 0xFFFFFFFF
+
         # Whether to serve a web client from the HTTP/HTTPS root resource.
         web_client: True
 
diff --git a/synapse/config/workers.py b/synapse/config/workers.py
index 99d5d8aaeb..c5a5a8919c 100644
--- a/synapse/config/workers.py
+++ b/synapse/config/workers.py
@@ -33,6 +33,7 @@ class WorkerConfig(Config):
         self.worker_name = config.get("worker_name", self.worker_app)
 
         self.worker_main_http_uri = config.get("worker_main_http_uri", None)
+        self.worker_cpu_affinity = config.get("worker_cpu_affinity")
 
         if self.worker_listeners:
             for listener in self.worker_listeners:
diff --git a/synapse/python_dependencies.py b/synapse/python_dependencies.py
index ed7f1c89ad..1d902dc38d 100644
--- a/synapse/python_dependencies.py
+++ b/synapse/python_dependencies.py
@@ -40,6 +40,7 @@ REQUIREMENTS = {
     "pymacaroons-pynacl": ["pymacaroons"],
     "msgpack-python>=0.3.0": ["msgpack"],
     "phonenumbers>=8.2.0": ["phonenumbers"],
+    "affinity": ["affinity"],
 }
 CONDITIONAL_REQUIREMENTS = {
     "web_client": {