LINUX.ORG.RU

conduit-network и утечки памяти: как правильно готовить?

 


0

5

Написан сервер, который принимает на вход строки и возвращает их в верхнем регистре:

import Data.Conduit
import Data.Conduit.Network 

import Data.ByteString.Char8 as BS
import Control.Monad.IO.Class

import qualified Data.Conduit.List as CL
import qualified Data.Conduit.Binary as CB
import Data.Conduit.Text
import Data.Text (toUpper)

main :: IO ()
main = runTCPServer (serverSettings 4000 HostIPv4) echoApp

echoApp :: Application IO
echoApp appData = appSource appData $= upperConduit $$ appSink appData

upperConduit :: Conduit ByteString IO ByteString
upperConduit = decode utf8 =$= CL.map toUpper =$= encode utf8

Компилируем:

ghc -O2 -rtsopts server.hs

и прогоняем через него файл размером в 174 Мб:

cat test.txt | nc localhost 4000

После окончания прогона сервер съедает до 400 Мб памяти и не освобождает её.

14,931,590,048 bytes allocated in the heap
      56,583,656 bytes copied during GC
     145,399,256 bytes maximum residency (11 sample(s))
     181,088,520 bytes maximum slop
             431 MB total memory in use (65 MB lost due to fragmentation)

Если запустить в параллель 2-3 таких прогона, то съедается в несколько раз больше памяти.

Почему так происходит и как правильно реализовать работу с кондуитами в данном случае?


собери с -prof и запусти с +RTS -hc, оно тебе граф выдаст где именно память юзается.

hateyoufeel ★★★★★
()

прогони профилировщик, чтобы поглядеть какие типы данных место жрут. Не смотря самоме, есть предположение, что он пытается весь траффик задекодить, а не чанками.

qnikst ★★★★★
()
Ответ на: комментарий от qnikst

Похоже на то.

На графике 2 типа: ARR_WORDS и ByteString. Первый как раз всё и выжирает, причём, в линейной прогрессии.

Чтобы чанками делилось, необходимо нарезать, скажем, построчно, с помощью Data.Conduit.Binary.lines? А если разделителей в потоке данных не будет, что тогда?

PS Кстати, нужный ключ для профилировщика не -hc , а -hy.

HolyBoy
() автор топика
Последнее исправление: HolyBoy (всего исправлений: 1)
Ответ на: комментарий от HolyBoy

не смогу сразу подсказать, я кондуиты давно не трогал, смысл должен быть такой: 'appSource appData $=' выдает тебе чанки текста, 'decode' переводит, в utf-8 что может, это или весь текст или чутка останется (leftover), тогда в на след шаге декодится этот чуток и потом остальное, далее это передается в в conduit который поднимает в верхний региств, потом в encode.

Проще в cafe, спросить или в haskell-streaming если эта гуглогруппа жива ещё. Если ответят - отпишись тут.

qnikst ★★★★★
()

Сделал ровно как ты сказал. Получил 1 MB total memory in use.

1) ghc-pkg list | grep conduit

2) Как конкретно ты запускал, как останавливал?

Miguel ★★★★★
()
Ответ на: комментарий от HolyBoy

Очень любопытно. У тебя версии даже посвежее. Либо Снойман что-то наглючил, либо оно ОС-зависимое, либо где. Ща обновлюсь и проверю ещё разок.

Miguel ★★★★★
()
Ответ на: комментарий от Miguel

Значит, так. На старых версиях (conduit-1.0.12, network-conduit-1.0.2.1) всё пучком. На новых — вот такая вот шняга.

Мой тебе совет: напиши Снойману (мейнтейнеру кондуитов), с указанием точной последовательности шагов. Он эту шнягу лучше знает, пусть сам и поправляет.

И проверь, что со старыми версиями у тебя работает.

Miguel ★★★★★
()
Последнее исправление: Miguel (всего исправлений: 1)
Ответ на: комментарий от Miguel

жалко, тогда точно в новый сноймано пакет лезть надо (text-stream-decode) но разбираться в нём уж совсем не хочется.

qnikst ★★★★★
()
Ответ на: комментарий от Miguel

Понял.

Хорошо, напишу и откачусь. Спасибо большое всем за помощь, а то я уже про себя думать стал плохо.

HolyBoy
() автор топика
Ответ на: комментарий от HolyBoy

Написал. О результате, если будет, напишу тут же.

HolyBoy
() автор топика
Ответ на: комментарий от qnikst

Да, он сказал, что проблема в text-stream-decode была. Поправил и выложил свежую версию 0.1.0.4. Я проверил с ней, влил 4-5 копий файла с таким результатом:

99,088,917,560 bytes allocated in the heap 
     290,165,088 bytes copied during GC  
         177,712 bytes maximum residency (9746 sample(s))
         101,888 bytes maximum slop                                    
               2 MB total memory in use (1 MB lost due to fragmentation)

Можно в оверлее запилить эту версию. У меня подошёл ебилд от предыдущей нормально.

HolyBoy
() автор топика
Последнее исправление: HolyBoy (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.