diff --git a/.env.sample b/.env.sample index 9c912cd503..619215729c 100644 --- a/.env.sample +++ b/.env.sample @@ -39,5 +39,6 @@ TELEGRAPH_TOKEN=" #MANAGER_PRIVILEGED=1 # default: 0 #NO_UVLOOP=1 # default: 0 #MULTIPROCESSING=1 # default: 0 +#EXECUTOR_NICENESS_INCREMENT=5 # default: 2 #DEBUG=1 # debug logging, default: 0 # ↑------ Advanced settings ------↑ # diff --git a/docker-compose.yml.sample b/docker-compose.yml.sample index 03c99ebb7f..187c43e74b 100644 --- a/docker-compose.yml.sample +++ b/docker-compose.yml.sample @@ -49,5 +49,6 @@ services: #- MANAGER_PRIVILEGED=1 # default: 0 #- NO_UVLOOP=1 # default: 0 #- MULTIPROCESSING=1 # default: 0 + #- EXECUTOR_NICENESS_INCREMENT=5 # default: 2 #- DEBUG=1 # debug logging, default: 0 # ↑------ Advanced settings ------↑ # \ No newline at end of file diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 51dd475660..eae30b677b 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -4,7 +4,7 @@ ### Enhancements -- **Set niceness for subprocesses/threads**: (Unix only) Nice subprocesses and/or threads to improve the responsiveness of the main process. +- **Set niceness for subprocesses/threads**: (Unix only) Nice subprocesses and/or threads to improve the responsiveness of the main process. This is tunable via the environment variable `EXECUTOR_NICENESS_INCREMENT`. ## v2.4.1: Minor enhancements, bug fixes, and Happy New Year! diff --git a/docs/CHANGELOG.zh.md b/docs/CHANGELOG.zh.md index 7fae666112..910e206a32 100644 --- a/docs/CHANGELOG.zh.md +++ b/docs/CHANGELOG.zh.md @@ -4,7 +4,7 @@ ### 增强 -- **为子进程/线程设置 nice 值**: (仅限 Unix) 为子进程和/或线程提升 nice 值以改进主进程的响应性。 +- **为子进程/线程设置 nice 值**: (仅限 Unix) 为子进程和/或线程提升 nice 值以改进主进程的响应性。这可通过环境变量 `EXECUTOR_NICENESS_INCREMENT` 调节。 ## v2.4.1: 次要的增强和 bug 修复,以及新年快乐! diff --git a/docs/advanced-settings.md b/docs/advanced-settings.md index c0cd58ef85..87cc16a314 100644 --- a/docs/advanced-settings.md +++ b/docs/advanced-settings.md @@ -43,18 +43,19 @@ ### Misc settings -| Key | Description | Example | Default | -|----------------------|---------------------------------------------------------------------------|-----------------------------------------------|-------------------------------------------------| -| `MULTIUSER` | Enable multi-user feature or not? | `0` | `1` | -| `CRON_SECOND` | Run the feed monitoring task at the n-th second of each minute? (0-59) | `30` | `0` | -| `IMG_RELAY_SERVER` | Media relay server URL | `https://wsrv.nl/?url=` | `https://rsstt-img-relay.rongrong.workers.dev/` | -| `IMAGES_WESERV_NL` | https://github.com/weserv/images instance | `https://t0.nl/` | `https://wsrv.nl/` | -| `DATABASE_URL` | Database URL [^7] | `postgres://user:pass@example.com:5432/table` | `sqlite://path/to/config/db.sqlite3` | -| `TABLE_TO_IMAGE` | Convert tables to image (causing higher CPU load) or just drop them? | `1` | `0` | -| `MANAGER_PRIVILEGED` | Allow the bot manager to manipulate any users' subscriptions or not? [^8] | `1` | `0` | -| `NO_UVLOOP` | Never enable `uvloop` (even if it is found) or not? | `1` | `0` | -| `MULTIPROCESSING` | Enable multiprocessing (up to `min(3, CPU_COUNT)`) or not? [^9] | `1` | `0` | -| `DEBUG` | Enable debug logging or not? | `1` | `0` | +| Key | Description | Example | Default | +|-------------------------------|-----------------------------------------------------------------------------|-----------------------------------------------|-------------------------------------------------| +| `MULTIUSER` | Enable multi-user feature or not? | `0` | `1` | +| `CRON_SECOND` | Run the feed monitoring task at the n-th second of each minute? (0-59) | `30` | `0` | +| `IMG_RELAY_SERVER` | Media relay server URL | `https://wsrv.nl/?url=` | `https://rsstt-img-relay.rongrong.workers.dev/` | +| `IMAGES_WESERV_NL` | https://github.com/weserv/images instance | `https://t0.nl/` | `https://wsrv.nl/` | +| `DATABASE_URL` | Database URL [^7] | `postgres://user:pass@example.com:5432/table` | `sqlite://path/to/config/db.sqlite3` | +| `TABLE_TO_IMAGE` | Convert tables to image (causing higher CPU load) or just drop them? | `1` | `0` | +| `MANAGER_PRIVILEGED` | Allow the bot manager to manipulate any users' subscriptions or not? [^8] | `1` | `0` | +| `NO_UVLOOP` | Never enable `uvloop` (even if it is found) or not? | `1` | `0` | +| `MULTIPROCESSING` | Enable multiprocessing (up to `min(3, CPU_COUNT)`) or not? [^9] | `1` | `0` | +| `EXECUTOR_NICENESS_INCREMENT` | The niceness increment of subprocesses (if `MULTIPROCESSING=1`) and threads | `5` | `2` | +| `DEBUG` | Enable debug logging or not? | `1` | `0` | ## Manager options diff --git a/src/aio_helper.py b/src/aio_helper.py index cc78f2c5f1..ed74f037b4 100644 --- a/src/aio_helper.py +++ b/src/aio_helper.py @@ -43,11 +43,13 @@ def _process_exit(_signum, _frame): def _common_initializer(): if hasattr(os, 'nice'): try: - niceness = os.nice(1) # nice processes/threads + niceness = os.nice(env.EXECUTOR_NICENESS_INCREMENT) except Exception as e: logger.warning('Failed to nice subprocess/thread', exc_info=e) else: logger.debug(f'The niceness of the subprocess/thread has been set to {niceness}') + elif env.EXECUTOR_NICENESS_INCREMENT: + logger.warning('The current platform does not support nice(), ignoring EXECUTOR_NICENESS_INCREMENT') logger.debug('Subprocess/thread initialized') @@ -82,6 +84,9 @@ def init(): ) ) if aioThreadExecutor and aioProcessExecutor else None + if env.EXECUTOR_NICENESS_INCREMENT < 0: + logger.warning('Lowering the niceness of subprocesses/threads may impact the performance of the main process') + # initialize all subprocesses/threads now # here we use sleep to ensure all subprocesses/threads are launched futures: list[Future] = [] diff --git a/src/env.py b/src/env.py index 91c69bca3c..90b381a289 100644 --- a/src/env.py +++ b/src/env.py @@ -250,6 +250,7 @@ def __list_parser(var: Optional[str]) -> list[str]: LAZY_MEDIA_VALIDATION: Final = __bool_parser(os.environ.get('LAZY_MEDIA_VALIDATION')) NO_UVLOOP: Final = __bool_parser(os.environ.get('NO_UVLOOP')) MULTIPROCESSING: Final = __bool_parser(os.environ.get('MULTIPROCESSING')) +EXECUTOR_NICENESS_INCREMENT: Final = int(os.environ.get('EXECUTOR_NICENESS_INCREMENT') or (2 * hasattr(os, 'nice'))) DEBUG: Final = __bool_parser(os.environ.get('DEBUG')) __configure_logging( # config twice to make .env file work level=colorlog.DEBUG if DEBUG else colorlog.INFO,