Haskellの実行速度
haskell vs その他の言語 - ながとの日記 という記事を見て、へぇーと思ってみてたのですが、元記事のコードの次の2つが何故これほどまでに違うのか、ちょっと気になったのでコンパイルだけして実際に確認してみます。(2つ目のはBangPatternの言語拡張のとこだけ削除)
import Control.Monad import qualified Data.HashTable as H main = do m <- H.new (==) H.hashInt forM_ [1..10000000] $ \n -> H.insert m n n v <- H.lookup m 100 print v
import qualified Data.HashTable as H import Data.Maybe eqInt :: Int -> Int -> Bool eqInt a b = a == b type HT = H.HashTable Int Int n = 1000000 loadHashtable :: HT -> IO () loadHashtable ht = work n where work :: Int -> IO () work i = do if i < 0 then return () else do H.insert ht i i work (i-1) main = do h <- H.new eqInt H.hashInt loadHashtable h i <- (H.lookup h 100) >>= (return . show . fromJust) putStrLn i
確かに後者のほうが圧倒的に速いです。恐らく違いは数字の列挙の方法にあり、前者は巨大なリストの走査で、後者はループカウンタの利用、ということなのでしょうか。
ただ現実問題として毎回後者のように書くのもアレなので、アクション部分を入れ替えられる高階関数を用意したほうが良さそうですね。
forIntM_ :: Int -> (Int -> IO ()) -> IO () forIntM_ n act = work n where work :: Int -> IO () work i = do if i < 0 then return () else do act i work (i-1) loadHashtable :: HT -> IO () loadHashtable ht = forIntM_ n (\i -> H.insert ht i i)