From 21d3476bd918a6af95829579af7694c5f5ff53d1 Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Fri, 18 Jul 2025 11:23:06 -0600 Subject: [PATCH] Require setting process priority for FrigateProcess (#19207) --- frigate/const.py | 6 ++++++ frigate/embeddings/__init__.py | 9 +++++++-- frigate/events/audio.py | 5 ++++- frigate/object_detection/base.py | 3 ++- frigate/output/output.py | 6 ++++-- frigate/record/export.py | 3 ++- frigate/record/record.py | 8 +++++++- frigate/review/review.py | 8 +++++++- frigate/util/classification.py | 8 +++++++- frigate/util/process.py | 4 ++++ frigate/video.py | 15 +++++++++++++-- 11 files changed, 63 insertions(+), 12 deletions(-) diff --git a/frigate/const.py b/frigate/const.py index f4bfee3d1..b252a3a75 100644 --- a/frigate/const.py +++ b/frigate/const.py @@ -113,6 +113,12 @@ UPDATE_EMBEDDINGS_REINDEX_PROGRESS = "handle_embeddings_reindex_progress" UPDATE_BIRDSEYE_LAYOUT = "update_birdseye_layout" NOTIFICATION_TEST = "notification_test" +# IO Nice Values + +PROCESS_PRIORITY_HIGH = 0 +PROCESS_PRIORITY_MED = 10 +PROCESS_PRIORITY_LOW = 19 + # Stats Values FREQUENCY_STATS_POINTS = 15 diff --git a/frigate/embeddings/__init__.py b/frigate/embeddings/__init__.py index f3acbbcf7..abee748d0 100644 --- a/frigate/embeddings/__init__.py +++ b/frigate/embeddings/__init__.py @@ -13,7 +13,7 @@ from pathvalidate import ValidationError, sanitize_filename from frigate.comms.embeddings_updater import EmbeddingsRequestEnum, EmbeddingsRequestor from frigate.config import FrigateConfig -from frigate.const import CONFIG_DIR, FACE_DIR +from frigate.const import CONFIG_DIR, FACE_DIR, PROCESS_PRIORITY_HIGH from frigate.data_processing.types import DataProcessorMetrics from frigate.db.sqlitevecq import SqliteVecQueueDatabase from frigate.models import Event @@ -34,7 +34,12 @@ class EmbeddingProcess(FrigateProcess): metrics: DataProcessorMetrics | None, stop_event: MpEvent, ) -> None: - super().__init__(stop_event, name="frigate.embeddings_manager", daemon=True) + super().__init__( + stop_event, + PROCESS_PRIORITY_HIGH, + name="frigate.embeddings_manager", + daemon=True, + ) self.config = config self.metrics = metrics diff --git a/frigate/events/audio.py b/frigate/events/audio.py index f99e6fe41..8446ca48d 100644 --- a/frigate/events/audio.py +++ b/frigate/events/audio.py @@ -29,6 +29,7 @@ from frigate.const import ( AUDIO_MAX_BIT_RANGE, AUDIO_MIN_CONFIDENCE, AUDIO_SAMPLE_RATE, + PROCESS_PRIORITY_HIGH, ) from frigate.data_processing.common.audio_transcription.model import ( AudioTranscriptionModelRunner, @@ -90,7 +91,9 @@ class AudioProcessor(FrigateProcess): camera_metrics: DictProxy, stop_event: MpEvent, ): - super().__init__(stop_event, name="frigate.audio_manager", daemon=True) + super().__init__( + stop_event, PROCESS_PRIORITY_HIGH, name="frigate.audio_manager", daemon=True + ) self.camera_metrics = camera_metrics self.cameras = cameras diff --git a/frigate/object_detection/base.py b/frigate/object_detection/base.py index 32f33ffa5..921f88b46 100644 --- a/frigate/object_detection/base.py +++ b/frigate/object_detection/base.py @@ -12,6 +12,7 @@ from frigate.comms.object_detector_signaler import ( ObjectDetectorSubscriber, ) from frigate.config import FrigateConfig +from frigate.const import PROCESS_PRIORITY_HIGH from frigate.detectors import create_detector from frigate.detectors.detector_config import ( BaseDetectorConfig, @@ -97,7 +98,7 @@ class DetectorRunner(FrigateProcess): detector_config: BaseDetectorConfig, stop_event: MpEvent, ) -> None: - super().__init__(stop_event, name=name, daemon=True) + super().__init__(stop_event, PROCESS_PRIORITY_HIGH, name=name, daemon=True) self.detection_queue = detection_queue self.cameras = cameras self.avg_speed = avg_speed diff --git a/frigate/output/output.py b/frigate/output/output.py index 34c9e33c0..4d7ff2466 100644 --- a/frigate/output/output.py +++ b/frigate/output/output.py @@ -22,7 +22,7 @@ from frigate.config.camera.updater import ( CameraConfigUpdateEnum, CameraConfigUpdateSubscriber, ) -from frigate.const import CACHE_DIR, CLIPS_DIR +from frigate.const import CACHE_DIR, CLIPS_DIR, PROCESS_PRIORITY_MED from frigate.output.birdseye import Birdseye from frigate.output.camera import JsmpegCamera from frigate.output.preview import PreviewRecorder @@ -74,7 +74,9 @@ def check_disabled_camera_update( class OutputProcess(FrigateProcess): def __init__(self, config: FrigateConfig, stop_event: MpEvent) -> None: - super().__init__(stop_event, name="frigate.output", daemon=True) + super().__init__( + stop_event, PROCESS_PRIORITY_MED, name="frigate.output", daemon=True + ) self.config = config def run(self) -> None: diff --git a/frigate/record/export.py b/frigate/record/export.py index 4eadbf1bd..f6e36d998 100644 --- a/frigate/record/export.py +++ b/frigate/record/export.py @@ -21,6 +21,7 @@ from frigate.const import ( EXPORT_DIR, MAX_PLAYLIST_SECONDS, PREVIEW_FRAME_TYPE, + PROCESS_PRIORITY_LOW, ) from frigate.ffmpeg_presets import ( EncodeTypeEnum, @@ -36,7 +37,7 @@ TIMELAPSE_DATA_INPUT_ARGS = "-an -skip_frame nokey" def lower_priority(): - os.nice(10) + os.nice(PROCESS_PRIORITY_LOW) class PlaybackFactorEnum(str, Enum): diff --git a/frigate/record/record.py b/frigate/record/record.py index b04a68e8c..624ed6e9a 100644 --- a/frigate/record/record.py +++ b/frigate/record/record.py @@ -6,6 +6,7 @@ from multiprocessing.synchronize import Event as MpEvent from playhouse.sqliteq import SqliteQueueDatabase from frigate.config import FrigateConfig +from frigate.const import PROCESS_PRIORITY_HIGH from frigate.models import Recordings, ReviewSegment from frigate.record.maintainer import RecordingMaintainer from frigate.util.process import FrigateProcess @@ -15,7 +16,12 @@ logger = logging.getLogger(__name__) class RecordProcess(FrigateProcess): def __init__(self, config: FrigateConfig, stop_event: MpEvent) -> None: - super().__init__(stop_event, name="frigate.recording_manager", daemon=True) + super().__init__( + stop_event, + PROCESS_PRIORITY_HIGH, + name="frigate.recording_manager", + daemon=True, + ) self.config = config def run(self) -> None: diff --git a/frigate/review/review.py b/frigate/review/review.py index 917a53a4b..c00c302a2 100644 --- a/frigate/review/review.py +++ b/frigate/review/review.py @@ -4,6 +4,7 @@ import logging from multiprocessing.synchronize import Event as MpEvent from frigate.config import FrigateConfig +from frigate.const import PROCESS_PRIORITY_MED from frigate.review.maintainer import ReviewSegmentMaintainer from frigate.util.process import FrigateProcess @@ -12,7 +13,12 @@ logger = logging.getLogger(__name__) class ReviewProcess(FrigateProcess): def __init__(self, config: FrigateConfig, stop_event: MpEvent) -> None: - super().__init__(stop_event, name="frigate.review_segment_manager", daemon=True) + super().__init__( + stop_event, + PROCESS_PRIORITY_MED, + name="frigate.review_segment_manager", + daemon=True, + ) self.config = config def run(self) -> None: diff --git a/frigate/util/classification.py b/frigate/util/classification.py index 533c1345a..87942a916 100644 --- a/frigate/util/classification.py +++ b/frigate/util/classification.py @@ -8,7 +8,12 @@ import numpy as np from frigate.comms.embeddings_updater import EmbeddingsRequestEnum, EmbeddingsRequestor from frigate.comms.inter_process import InterProcessRequestor -from frigate.const import CLIPS_DIR, MODEL_CACHE_DIR, UPDATE_MODEL_STATE +from frigate.const import ( + CLIPS_DIR, + MODEL_CACHE_DIR, + UPDATE_MODEL_STATE, + PROCESS_PRIORITY_LOW, +) from frigate.log import redirect_output_to_logger from frigate.types import ModelStatusTypesEnum from frigate.util.process import FrigateProcess @@ -24,6 +29,7 @@ class ClassificationTrainingProcess(FrigateProcess): def __init__(self, model_name: str) -> None: super().__init__( stop_event=None, + priority=PROCESS_PRIORITY_LOW, name=f"model_training:{model_name}", ) self.model_name = model_name diff --git a/frigate/util/process.py b/frigate/util/process.py index 830818d4d..b9fede44e 100644 --- a/frigate/util/process.py +++ b/frigate/util/process.py @@ -1,6 +1,7 @@ import faulthandler import logging import multiprocessing as mp +import os import threading from logging.handlers import QueueHandler from multiprocessing.synchronize import Event as MpEvent @@ -16,6 +17,7 @@ class BaseProcess(mp.Process): def __init__( self, stop_event: MpEvent, + priority: int, *, name: Optional[str] = None, target: Optional[Callable] = None, @@ -23,6 +25,7 @@ class BaseProcess(mp.Process): kwargs: dict = {}, daemon: Optional[bool] = None, ): + self.priority = priority self.stop_event = stop_event super().__init__( name=name, target=target, args=args, kwargs=kwargs, daemon=daemon @@ -47,6 +50,7 @@ class FrigateProcess(BaseProcess): self.__log_queue = frigate.log.log_listener.queue def pre_run_setup(self, logConfig: LoggerConfig | None = None) -> None: + os.nice(self.priority) setproctitle(self.name) threading.current_thread().name = f"process:{self.name}" faulthandler.enable() diff --git a/frigate/video.py b/frigate/video.py index 5d7185d10..2754a12cd 100755 --- a/frigate/video.py +++ b/frigate/video.py @@ -23,6 +23,7 @@ from frigate.const import ( CACHE_DIR, CACHE_SEGMENT_FORMAT, REQUEST_REGION_GRID, + PROCESS_PRIORITY_HIGH, ) from frigate.log import LogPipe from frigate.motion import MotionDetector @@ -445,7 +446,12 @@ class CameraCapture(FrigateProcess): camera_metrics: CameraMetrics, stop_event: MpEvent, ) -> None: - super().__init__(stop_event, name=f"frigate.capture:{config.name}", daemon=True) + super().__init__( + stop_event, + PROCESS_PRIORITY_HIGH, + name=f"frigate.capture:{config.name}", + daemon=True, + ) self.config = config self.shm_frame_count = shm_frame_count self.camera_metrics = camera_metrics @@ -478,7 +484,12 @@ class CameraTracker(FrigateProcess): region_grid: list[list[dict[str, Any]]], stop_event: MpEvent, ) -> None: - super().__init__(stop_event, name=f"frigate.process:{config.name}", daemon=True) + super().__init__( + stop_event, + PROCESS_PRIORITY_HIGH, + name=f"frigate.process:{config.name}", + daemon=True, + ) self.config = config self.model_config = model_config self.labelmap = labelmap