Si consideri il seguente programma giocattolo che calcola tutte le combinazioni di sostituzioni di caratteri in una parola, del tipo spesso utilizzato nelle password.Perché questo programma Haskell perde spazio quando compilato con ottimizzazioni?
import Data.Char (isLower, toUpper)
variants :: String -> [String]
variants "" = [""]
variants (c:s) = [c':s' | c' <- subst c, s' <- variants s]
where subst 'a' = "[email protected]"
subst 'e' = "eE3"
subst 'i' = "iI1"
subst 'l' = "lL1"
subst 'o' = "oO0"
subst 's' = "sS$5"
subst 'z' = "zZ2"
subst x | isLower x = [x, toUpper x]
subst x = [x]
main :: IO()
main = putStrLn $ show $ length $ variants "redistributables"
posso compilare con e senza ottimizzazioni:
$ ghc -fforce-recomp -Wall Test.hs -o test0
[1 of 1] Compiling Main (Test.hs, Test.o)
Linking test0 ...
$ ghc -fforce-recomp -O -Wall Test.hs -o test1
[1 of 1] Compiling Main (Test.hs, Test.o)
Linking test1 ...
Ora test0
e test1
produrre la stessa uscita, ma test1
utilizza molta più memoria e trascorre la maggior parte del suo tempo in garbage collection:
$ ./test0 +RTS -s 2>&1 | grep total
2 MB total memory in use (0 MB lost due to fragmentation)
Productivity 93.2% of total user, 93.3% of total elapsed
$ ./test1 +RTS -s 2>&1 | grep total
188 MB total memory in use (0 MB lost due to fragmentation)
Productivity 15.0% of total user, 15.0% of total elapsed
Perché?
Sto utilizzando GHC 7.4.1; Probabilmente dovrei usare un compilatore più recente, ma questo è quello che ho a portata di mano in questo momento, e l'errore probabilmente ricade comunque su di me.
7.4 è piuttosto antico a questo punto, almeno utilizza 7.8 se non 7.10. Per rispondere a questo probabilmente dovrai passare '-ddump-simpl' per ottenere l'output principale, quindi passare attraverso quello per capire esattamente qual è la differenza. – bheklilr
@bheklilr Fatto. Ovviamente il Core generato è molto diverso, ma è davvero difficile per un principiante Haskell districarsi e finora non ci sono riuscito. –
e cosa succede con -O2 flag? –