2015-05-13 18 views
12

Szukam możliwości optymalizacji w moim programie Haskell, kompilując się z -prof, ale nie wiem, jak interpretować centra kosztów, które zawierają elipsy. Co to są filter.(...) i jankRoulette.select.(...)?Co znaczy. (...) w raporcie .prof?

COST CENTRE    MODULE      %time %alloc 

filter.(...)    Forest      46.5 22.3 
set-union     Forest      22.5 4.1 
cache-lookup    Forest      16.0 0.1 
removeMany     MultiMapSet     3.7 1.9 
insertMany     MultiMapSet     3.3 1.8 
jankRoulette.select.(...) Forest      1.4 15.2 

I generowane że z: $ ghc --make -rtsopts -prof -auto-all main.hs && ./main +RTS -p && cat main.prof

Funkcja filter ma kilka definicji w where klauzuli, na przykład:

filter a b = blahblah where 
    foo = bar 
    bar = baz 
    baz = bing 

Ale ci wszyscy pojawiają się jako filter.foo, filter.bar, etc

Myślałem, że mogą być zagnieżdżone, ale wyrażenia, ale jankRoulette.select nie ma żadnych. Dodałem też dyrektywy SCC przed większością z nich, bez żadnego z tych centrów powstawania kosztów.

Ponieważ większość czasu spędzam w filter.(...), chciałbym wiedzieć, co to jest. :)

+1

Jako że komentarz 'TODO' w cytacie Bennofsa powinien sugerować, raporty profilera GHC (i prawie wszystko, co kompilator wypisze) powinny zawsze być połączone z wynikiem' ghc --version'. – dfeuer

+0

Dzięki za przypomnienie! Jeśli chodzi o potomstwo, to na pewno pracuję nad systemem kompilacji Glorious Glasgow Haskell, wersja 7.8.1. – alltom

Odpowiedz

7

TL; DR: GHC generuje to, gdy dopasowujesz wzorzec w wiązaniu let, takim jak let (x,y) = c. Koszt oszacowania c jest śledzony przez centrum kosztów ... (ponieważ nie ma w nim unikalnej nazwy) `.


Więc jak to znalazłem? grep dla (...) w kodzie źródłowym GHC znajdzie następujące (od kompilatora/deSugar/Coverage.hs):

-- TODO: Revisit this 
addTickLHsBind (L pos ([email protected](PatBind { pat_lhs = lhs, pat_rhs = rhs }))) = do 
    let name = "(...)" 
    (fvs, rhs') <- getFreeVars $ addPathEntry name $ addTickGRHSs False False rhs 

    {- ... more code following, but not relevant to this purpose 
    -} 

Ten kod mówi nam, że musi coś zrobić z wiązaniami sygnatur. Tak więc możemy zrobić mały program testowy, aby sprawdzić zachowanie:

x :: Int 
(x:_) = reverse [1..1000000000] 

main :: IO() 
main = print x 

Następnie możemy uruchomić ten program z profilowania włączony. Rzeczywiście, GHC generuje następujący wynik:

COST CENTRE MODULE     no.  entries %time %alloc %time 

%alloc 
MAIN  MAIN      42   0 0.0 0.0 100.0 100.0 
CAF  Main      83   0 0.0 0.0 100.0 100.0 
    (...)  Main      86   1 100.0 100.0 100.0 100.0 
    x   Main      85   1 0.0 0.0  0.0 0.0 
    main  Main      84   1 0.0 0.0  0.0 0.0 

Okazuje się, że założenie z kodu było prawidłowe. Cały czas trwania programu jest analizowany pod kątem wyrażenia reverse [1..1000000000] i przypisywany do centrum kosztowego (...).

+0

Uwielbiam (i całkowicie współczuję) komentarz "TODO" tam: P. –

+0

Wniosek: Aby ujednoznacznić miejsca powstawania kosztów, podaj wartości przed dopasowaniem do wzorca, np. '(X: _) = foo gdzie foo = odwróć [1..10000000]'. Świetna odpowiedź, Bennofs, wielkie dzięki! – alltom