[Haskell] устранение утечек памяти, FastCGI

Модератор: Модераторы разделов

Аватара пользователя
minoru-kun
Сообщения: 621
ОС: Debian GNU/Linux

[Haskell] устранение утечек памяти, FastCGI

Сообщение minoru-kun »

Имею следующий кусок кода:

Код:

import Network.FastCGI import Random import Data.Maybe import Control.Monad import Control.Exception as E handleRequest :: StdGen -> CGI (Int,StdGen) handleRequest gen = do low <- getInput("low") high <- getInput("high") let rnd = randomR (read (fromJust low) :: Int,read (fromJust high) :: Int) gen liftIO $ (runOneFastCGI . output) (show (fst rnd)) return rnd main = do gen <- newStdGen let cgi_handler x = x >>= \(_,gen) -> handleRequest gen cgi_process x = x >>= \(result,_) -> output (show result) error_handler x = E.catch x (\err -> (runOneFastCGI . output) ("Error: " ++ show (err :: ErrorCall))) runFastCGI $ forever $ sequence_ $ iterate cgi_handler (return (1, gen))

Все бы хорошо, но течет оперативка (приблизительно 60мб за 100 000 обращений).
Я изменил код следующим образом:

Код:

import Network.FastCGI import Random import Data.Maybe import Control.Monad import Control.Exception as E handleRequest :: StdGen -> CGI (Int,StdGen) handleRequest gen = do low <- getInput("low") high <- getInput("high") let rnd = randomR (read (fromJust low) :: Int,read (fromJust high) :: Int) gen liftIO $ (runOneFastCGI . output) (show (fst rnd)) return rnd cgi_handler x = x >>= \(_,gen) -> handleRequest gen cgi_process x = x >>= \(result,_) -> output (show result) error_handler x = E.catch x (\err -> (runOneFastCGI . output) ("Error: " ++ show (err :: ErrorCall))) main = do gen <- newStdGen -- runFastCGI $ forever $ sequence_ $ iterate cgi_handler (return (1, gen)) runFastCGI $ cgi_process $ last $ take 50000 $ iterate cgi_handler (return (1, gen))

и скормил профайлеру:

Код: Выделить всё

minoru@debian:~/src$ ghc --make -prof -auto-all simplefcgi3.hs
[1 of 1] Compiling Main             ( simplefcgi3.hs, simplefcgi3.o )
Linking simplefcgi3 ...

Код: Выделить всё

#!/bin/bash
./simplefcgi3 +RTS -p

В результате получил вот такой дамп:

Код:

Fri May 14 11:22 2010 Time and Allocation Profiling Report (Final) simplefcgi3 +RTS -p -RTS total time = 0.04 secs (2 ticks @ 20 ms) total alloc = 5,894,808 bytes (excludes profiling overheads) COST CENTRE MODULE %time %alloc main Main 50.0 61.4 cgi_handler Main 50.0 37.3 individual inherited COST CENTRE MODULE no. entries %time %alloc %time %alloc MAIN MAIN 1 0 0.0 0.0 100.0 100.0 CAF Main 440 10 0.0 0.0 100.0 98.8 cgi_process Main 448 1 0.0 0.0 0.0 0.0 main Main 446 1 50.0 61.1 100.0 98.8 cgi_handler Main 449 49999 50.0 37.3 50.0 37.7 handleRequest Main 450 1 0.0 0.4 0.0 0.4 CAF Data.Typeable 438 1 0.0 0.0 0.0 0.0 CAF GHC.IO.Exception 432 9 0.0 0.1 0.0 0.1 CAF GHC.Read 417 1 0.0 0.0 0.0 0.0 CAF GHC.Exception 413 3 0.0 0.0 0.0 0.0 CAF Data.Maybe 412 2 0.0 0.0 0.0 0.0 CAF Text.Read.Lex 405 8 0.0 0.0 0.0 0.0 CAF Data.HashTable 379 2 0.0 0.0 0.0 0.0 CAF GHC.IO.Handle.FD 377 2 0.0 0.4 0.0 0.4 CAF System.Posix.Internals 376 1 0.0 0.0 0.0 0.0 CAF GHC.Conc 360 4 0.0 0.0 0.0 0.0 CAF GHC.IO.Handle.Internals 351 1 0.0 0.0 0.0 0.0 CAF GHC.IO.Encoding.Iconv 345 3 0.0 0.0 0.0 0.0 CAF System.Random 338 1 0.0 0.1 0.0 0.1 CAF Data.Fixed 332 2 0.0 0.0 0.0 0.0 CAF Data.Time.Clock.POSIX 330 2 0.0 0.0 0.0 0.0 CAF Data.Time.Clock.CTimeval 329 1 0.0 0.0 0.0 0.0 CAF Network.FastCGI 310 5 0.0 0.0 0.0 0.3 main Main 447 0 0.0 0.3 0.0 0.3 CAF Network.CGI.Protocol 309 7 0.0 0.1 0.0 0.1 CAF Control.Monad.Trans 287 1 0.0 0.0 0.0 0.0

Как видно, течет cgi_handler и main (очевидно, iterate, который его дергает. Как можно избавиться от течи? Использовать какой-нибудь MVar не хотелось бы.
Спасибо сказали: