2015-06-13 14 views
6

Wygląda na to, że IO Haskella jest relatywnie wolne.Jak poprawić wydajność Haskell IO?

Na przykład, porównując Haskell z Pythonem

#io.py 
import sys 
s=sys.stdin.read() 
sys.stdout.write(s) 

,

-- io.hs 
main = do 
    s <- getContents 
    putStr s 

Ich wydajność (gen.py pisze 512K danych do stdout):

wersji

Python:

$ time python gen.py | python io.py > /dev/null 

real 0m0.203s 
user 0m0.015s 
sys  0m0.000s 

Wersja Haskell:

$ time python gen.py | runhaskell io.hs > /dev/null 

real 0m0.562s 
user 0m0.015s 
sys  0m0.000s 

Wygląda na to, że Haskell jest znacznie niższy. Czy jest jakiś problem z moim testem? Czy jest to tylko nieodłączny problem Haskella?

Dzięki.

+3

Oba czasy to czas potrzebny do kompilacji program spróbować rozrządu 'gen.pyc' (skompilowany) vs skompilowany kod binarny z 'io.hs'. – chepner

Odpowiedz

6

Twój przykład jest powolny, ponieważ używa leniwego IO z String -s. Oba mają własne koszty ogólne.

W szczególności, String jest połączoną listą Char -s, dlatego ma dwa słowa narzutowe dla każdego znaku (jedno słowo dla znacznika konstruktora i jedno dla wskaźnika do przodu), a każda postać zajmuje co najmniej jedno słowo (jedno słowo dla cache low characters, trzy słowa dla uncached characters).

Ścisłe IO z wejściem tablicy bajtowej lub unicode jest znacznie szybsze. Spróbuj odniesienia następujące:

import qualified Data.ByteString as B 

main = B.putStr =<< B.getContents 

Albo co następuje:

import qualified Data.Text as T 
import qualified Data.Text.IO as T 

main = T.putStr =<< T.getContents 
+0

Obie wersje kosztują około 520 ms (około 10% poprawy). I myślę, że leniwy IO jest przestarzały ze względu na sposób wydawania zasobów? http://stackoverflow.com/questions/5892653/whats-so-bad-about-lazy-i-o – sqd

+1

Spróbuj skompilować z opcją -O2. –

+8

'runhaskell' jest zawsze powolny, bez względu na to, czym jest praca. GHC optymalizuje pliki wykonywalne, a nie prędkość interpretera. –