Ciao.
Allora sono andato a informarmi un po' sul profiling. Ho fatto dei tentativi su file
num.ls di \(3 \cdot 10^6\) righe, che possono essere poche, ma bastano a trarre delle conclusioni.
1. Tra
sumFile1 e
sumFile2 il confronto è impari: andando a vedere come sono implementate le funzioni di Prelude,
sum è strict, mentre nella seconda ci sono dei pezzi pigri.
2. La seconda implementazione è più lenta rispetto alla prima, ma di poco.
3. Sulla seconda versione ho più controllo sul processo di valutazione, e quindi sulla memoria.
Proviamo così allora:
- Codice:
-- sandbox.hs
{-# LANGUAGE BangPatterns #-}
import Control.Conditional (ifM)
import System.IO (Handle, hGetLine, hIsEOF, IOMode(..), withFile)
main :: IO ()
main = print =<< sumFile "num.ls"
sumFile :: FilePath -> IO Double
sumFile f = withFile f ReadMode (_sum 0)
where
_sum :: Double -> Handle -> IO Double
_sum !s hdl = ifM (hIsEOF hdl) (return s) $ do
x <- (fmap read . hGetLine) hdl
_sum (s+x) hdl
- Codice:
$ ghc -O -rtsopts sandbox.hs
$ for i in {1..3000000}; do echo $RANDOM >> num.ls; done
$ ./sandbox +RTS -sstderr
4.9164487364e10
16,747,949,904 bytes allocated in the heap
11,267,488 bytes copied during GC
53,592 bytes maximum residency (3 sample(s))
36,520 bytes maximum slop
0 MB total memory in use (0 MB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause
Gen 0 16060 colls, 0 par 0.087s 0.086s 0.0000s 0.0001s
Gen 1 3 colls, 0 par 0.001s 0.001s 0.0002s 0.0004s
INIT time 0.000s ( 0.000s elapsed)
MUT time 5.378s ( 5.411s elapsed)
GC time 0.088s ( 0.086s elapsed)
EXIT time 0.000s ( 0.000s elapsed)
Total time 5.466s ( 5.497s elapsed)
%GC time 0.0% (0.0% elapsed)
Alloc rate 3,114,094,493 bytes per MUT second
Productivity 98.4% of total user, 98.4% of total elapsed
Ho azzerato lo spazio consumato, ridotto ancora di più i tempi rispetto a
sumFile1 e la "productivity" si avvicina al 100% (mentre con
sumFile1 si sta al 91%). È tutta questione di strictness allora.
Per quanto riguarda ByteString: so che esiste e non è difficile passarci, ma la cosa era un esercizietto.