#haskell #concurrency #ghc
#haskell #параллелизм #ghc
Вопрос:
Серверная программа поддерживает длительные TCP-соединения со многими клиентами. Каждое клиентское соединение обслуживается потоком, созданным с forkIO
помощью . Сервер занимает много памяти при запуске, поэтому, естественно, я выполнил профилирование, чтобы выявить возможные утечки пространства. Однако, имея около 10 тыс. клиентов (следовательно, 10 тыс. потоков), результат показывает, что большая часть кучи на самом деле является стеком, выделяемым потоками. Если я правильно понимаю, это неудивительно, поскольку стек потока по умолчанию начинается с 1 кб и увеличивается на 32 кб. Поскольку это длительные потоки, эта память не будет GCed.
Мой вопрос: СТЕК занимает слишком много места, есть ли способ уменьшить его?
У меня были некоторые мысли по этому поводу: ранее я мог использовать API уведомлений о событиях из GHC для написания программы без использования потоков, однако, похоже, этот вариант больше невозможен, поскольку GHC прекратил экспорт некоторых функций обработки событий, таких как loop
. С другой стороны, такое изменение означает серьезный сдвиг в модели параллелизма (потоки против событий), что очень нежелательно, поскольку с потоками Haskell просто так приятно работать. Другой способ, который пришел мне в голову, — разделить / переписать потоки так, чтобы один поток выполнял все процедуры квитирования аутентификации, создавал новый поток и затем завершал работу. Мы надеемся, что новый поток, который будет продолжать цикл, не требует больше места в СТЕКЕ. Однако я не уверен, что эта идея правильная или выполнимая.
Комментарии:
1. Как насчет простого уменьшения размера фрагмента стека (из справки RTS:
-kc<size> Sets the stack chunk size (default 32k)
)?2. Выше мы видим 300M для СТЕКОВ. Разделив это на 10 тыс. потоков, мы получаем ~ 36 тыс. на поток. Не так уж и плохо, всего ~ 1 фрагмент на поток — исходя из этих цифр, предложение @ReidBarton выглядит довольно многообещающим.