Написан сервер, который принимает на вход строки и возвращает их в верхнем регистре:
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 таких прогона, то съедается в несколько раз больше памяти.
Почему так происходит и как правильно реализовать работу с кондуитами в данном случае?