From 9e86eda05ac590d82dd1c879be84cf8bd7d31d54 Mon Sep 17 00:00:00 2001 From: Stefan Agner Date: Mon, 1 Mar 2021 15:29:10 +0100 Subject: [PATCH] Adjust CPU runtime allocation to support multiple add-ons (#2655) Adjust realtime CPU runtime allocation to support multiple add-ons/plug-ins with the runtime flag set. The cpu.rt_runtime_us allocation is somewhat special as it allocates the guaranteed runtime. Hence we cannot simply allocate all time to each add-on. Unfortunately we cannot distribute the CPU time equally based on the number of add-ons as we don't know the number of add-ons which will use realtime ahead of time. Also adjusting at runtime is currenlty not supported by the Docker Python SDK (the underlying http API does however, so this would be a possible future improvement). This solution distributes the total available time of 950ms to up to 5 add-ons/plug-ins in equal slices. On a quad-core system this allows up to 760ms CPU time in the real-time scheduler per 1s (76% of one CPU) which should be sufficient for most cases. --- supervisor/const.py | 11 +++++++++++ supervisor/docker/addon.py | 3 ++- supervisor/docker/audio.py | 4 ++-- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/supervisor/const.py b/supervisor/const.py index 922ef8742..49c8d6b1b 100644 --- a/supervisor/const.py +++ b/supervisor/const.py @@ -32,6 +32,17 @@ DOCKER_NETWORK = "hassio" DOCKER_NETWORK_MASK = ip_network("172.30.32.0/23") DOCKER_NETWORK_RANGE = ip_network("172.30.33.0/24") +# This needs to match the dockerd --cpu-rt-runtime= argument. +DOCKER_CPU_RUNTIME_TOTAL = 950_000 + +# The rt runtimes are guarantees, hence we cannot allocate more +# time than available! Support up to 5 containers with equal time +# allocated. +# Note that the time is multiplied by CPU count. This means that +# a single container can schedule up to 950/5*4 = 760ms in RT priority +# on a quad core system. +DOCKER_CPU_RUNTIME_ALLOCATION = int(DOCKER_CPU_RUNTIME_TOTAL / 5) + DNS_SUFFIX = "local.hass.io" LABEL_ARCH = "io.hass.arch" diff --git a/supervisor/docker/addon.py b/supervisor/docker/addon.py index 4f33fee59..bae599cc4 100644 --- a/supervisor/docker/addon.py +++ b/supervisor/docker/addon.py @@ -14,6 +14,7 @@ import requests from ..addons.build import AddonBuild from ..const import ( + DOCKER_CPU_RUNTIME_ALLOCATION, ENV_TIME, ENV_TOKEN, ENV_TOKEN_HASSIO, @@ -285,7 +286,7 @@ class DockerAddon(DockerInterface): # If need CPU RT if self.addon.with_realtime: - return 950000 + return DOCKER_CPU_RUNTIME_ALLOCATION return None @property diff --git a/supervisor/docker/audio.py b/supervisor/docker/audio.py index a7e5198ee..14388eeb2 100644 --- a/supervisor/docker/audio.py +++ b/supervisor/docker/audio.py @@ -4,7 +4,7 @@ from typing import Dict, List, Optional import docker -from ..const import ENV_TIME, MACHINE_ID +from ..const import DOCKER_CPU_RUNTIME_ALLOCATION, ENV_TIME, MACHINE_ID from ..coresys import CoreSysAttributes from ..docker.const import Capabilities from ..hardware.const import PolicyGroup @@ -67,7 +67,7 @@ class DockerAudio(DockerInterface, CoreSysAttributes): """Limit CPU real-time runtime in microseconds.""" if not self.sys_docker.info.support_cpu_realtime: return None - return 950000 + return DOCKER_CPU_RUNTIME_ALLOCATION def _run(self) -> None: """Run Docker image.