Чрезмерное количество системных вызовов при использовании `threadDelay`
У меня есть несколько процессов Haskell, запущенных на производстве, с системой с 12 ядрами. Все процессы скомпилированы с помощью -threaded
и работают с 12 возможностями. Одна библиотека, которую они все используют, - это resource-pool
, которая поддерживает пул соединений с базой данных.
Интересно, что, хотя все процессы практически бездействуют, они потребляют около 2% процессорного времени. Осмотр одного из этих процессов с помощью strace -p $(pgrep processname) -f
показывает, что процесс выполняет необоснованное количество системных вызовов, даже если он не должен ничего делать. Чтобы взглянуть на вещи:
- Запуск strace в процессе с
-N2
в течение 5 секунд создает файл журнала 66K. - Запуск с (необоснованным)
-N64
дает журнал < <мегабайт > .
Таким образом, количество возможностей увеличивает количество системных вызовов, которые выдается решительно.
Копаем глубже, мы обнаруживаем, что resource-pool
запускает поток руны, который срабатывает каждую секунду, чтобы проверить, может ли он очистить некоторые ресурсы. Мы можем моделировать то же поведение с этой тривиальной программой.
module Main where
import Control.Concurrent
import Control.Monad (forever)
main :: IO ()
main = forever $ do
threadDelay (10 ^ 6)
Если я передаю -B
системе выполнения, я получаю звуковую обратную связь всякий раз, когда выдается GC, что в этом случае каждые 60 секунд.
Поэтому, когда я подавляю эти циклы GC, передавая -I0
в RTS, выполняющий команду strace
в процессе, выдает только около 70K больших файлов журнала. Поскольку процесс также запускает сервер scotty
, GC запускается, когда запросы поступают, поэтому они, похоже, происходят, когда они мне действительно нужны.
Поскольку мы собираемся увеличить количество процессов Haskell на этой машине на большую сумму в течение следующего года, мне было интересно, как сохранить их свободное время на разумном уровне. Очевидно, передача -I0
кажется довольно плохой идеей (?). Другая идея заключалась бы в том, чтобы просто уменьшить количество возможностей с 12 до, возможно, что-то вроде 4. Есть ли другой способ настроить RTS, чтобы я мог поддерживать процессы от записи до многих циклов ЦП на холостом ходу?