Skip to content
Snippets Groups Projects
Commit 10d8b701 authored by Richard van der Hoff's avatar Richard van der Hoff
Browse files

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.
parent 543c794a
No related branches found
No related tags found
No related merge requests found
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
import gc import gc
import logging import logging
import affinity
from daemonize import Daemonize from daemonize import Daemonize
from synapse.util import PreserveLoggingContext from synapse.util import PreserveLoggingContext
from synapse.util.rlimit import change_resource_limit from synapse.util.rlimit import change_resource_limit
...@@ -40,7 +41,8 @@ def start_worker_reactor(appname, config): ...@@ -40,7 +41,8 @@ def start_worker_reactor(appname, config):
config.gc_thresholds, config.gc_thresholds,
config.worker_pid_file, config.worker_pid_file,
config.worker_daemonize, config.worker_daemonize,
logger config.worker_cpu_affinity,
logger,
) )
...@@ -50,6 +52,7 @@ def start_reactor( ...@@ -50,6 +52,7 @@ def start_reactor(
gc_thresholds, gc_thresholds,
pid_file, pid_file,
daemonize, daemonize,
cpu_affinity,
logger, logger,
): ):
""" Run the reactor in the main process """ Run the reactor in the main process
...@@ -63,6 +66,7 @@ def start_reactor( ...@@ -63,6 +66,7 @@ def start_reactor(
gc_thresholds: gc_thresholds:
pid_file (str): name of pid file to write to if daemonize is True 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 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 logger (logging.Logger): logger instance to pass to Daemonize
""" """
...@@ -73,6 +77,9 @@ def start_reactor( ...@@ -73,6 +77,9 @@ def start_reactor(
# between the sentinel and `run` logcontexts. # between the sentinel and `run` logcontexts.
with PreserveLoggingContext(): with PreserveLoggingContext():
logger.info("Running") 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) change_resource_limit(soft_file_limit)
if gc_thresholds: if gc_thresholds:
gc.set_threshold(*gc_thresholds) gc.set_threshold(*gc_thresholds)
......
...@@ -442,6 +442,7 @@ def run(hs): ...@@ -442,6 +442,7 @@ def run(hs):
hs.config.gc_thresholds, hs.config.gc_thresholds,
hs.config.pid_file, hs.config.pid_file,
hs.config.daemonize, hs.config.daemonize,
hs.config.cpu_affinity,
logger, logger,
) )
......
...@@ -29,6 +29,7 @@ class ServerConfig(Config): ...@@ -29,6 +29,7 @@ class ServerConfig(Config):
self.user_agent_suffix = config.get("user_agent_suffix") self.user_agent_suffix = config.get("user_agent_suffix")
self.use_frozen_dicts = config.get("use_frozen_dicts", False) self.use_frozen_dicts = config.get("use_frozen_dicts", False)
self.public_baseurl = config.get("public_baseurl") 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 # Whether to send federation traffic out in this process. This only
# applies to some federation traffic, and so shouldn't be used to # applies to some federation traffic, and so shouldn't be used to
...@@ -147,6 +148,17 @@ class ServerConfig(Config): ...@@ -147,6 +148,17 @@ class ServerConfig(Config):
# When running as a daemon, the file to store the pid in # When running as a daemon, the file to store the pid in
pid_file: %(pid_file)s 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. # Whether to serve a web client from the HTTP/HTTPS root resource.
web_client: True web_client: True
......
...@@ -33,6 +33,7 @@ class WorkerConfig(Config): ...@@ -33,6 +33,7 @@ class WorkerConfig(Config):
self.worker_name = config.get("worker_name", self.worker_app) self.worker_name = config.get("worker_name", self.worker_app)
self.worker_main_http_uri = config.get("worker_main_http_uri", None) 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: if self.worker_listeners:
for listener in self.worker_listeners: for listener in self.worker_listeners:
......
...@@ -40,6 +40,7 @@ REQUIREMENTS = { ...@@ -40,6 +40,7 @@ REQUIREMENTS = {
"pymacaroons-pynacl": ["pymacaroons"], "pymacaroons-pynacl": ["pymacaroons"],
"msgpack-python>=0.3.0": ["msgpack"], "msgpack-python>=0.3.0": ["msgpack"],
"phonenumbers>=8.2.0": ["phonenumbers"], "phonenumbers>=8.2.0": ["phonenumbers"],
"affinity": ["affinity"],
} }
CONDITIONAL_REQUIREMENTS = { CONDITIONAL_REQUIREMENTS = {
"web_client": { "web_client": {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment