Haskell Hashtable性能

And*_*sky 7 haskell hashmap

我试图在Haskell中使用hashtables包的哈希表,并发现我无法接近Python的性能.我怎样才能达到类似的性能?是否有可能给出当前的Haskell库和编译器?如果没有,那么潜在的问题是什么?

这是我的Python代码:

y = {}
for x in xrange(10000000):
    y[x] = x
print y[100]
Run Code Online (Sandbox Code Playgroud)

这是我相应的Haskell代码:

import qualified Data.HashTable.IO as H
import Control.Monad

main = do
  y <- H.new :: IO (H.CuckooHashTable Int Int)
  forM_ [1..10000000] $ \x -> H.insert y x x
  H.lookup y 100 >>= print
Run Code Online (Sandbox Code Playgroud)

这是另一个使用的版本Data.Map,对我来说比两者都慢:

import qualified Data.Map as Map
import Data.List
import Control.Monad
main = do
  let m = foldl' (\m x -> Map.insert x x m) Map.empty [1..10000000]
  print $ Map.lookup 100 m
Run Code Online (Sandbox Code Playgroud)

有趣的是,Data.HashMap表现非常糟糕:

import qualified Data.HashMap.Strict as Map
import Data.List
main = do
  let m = foldl' (\m x -> Map.insert x x m) Map.empty [1..10000000]
  print $ Map.lookup 100 m
Run Code Online (Sandbox Code Playgroud)

我的怀疑是Data.HashMap表现不好,因为不像Data.Map,它不是脊柱严格的(我认为),所以foldl'只是一个foldl,伴随着相关的thunk积累问题.

请注意,我已经使用-prof并验证了大部分的时间花费在hashtablesData.Map代码,不上forM或类似的东西.所有代码都是用-O2其他参数编译的.

小智 11

正如reddit.com/u/cheecheeo 在这里建议的那样,使用Data.Judy,您将获得与您的特定微基准测试相似的性能:

module Main where

import qualified Data.Judy as J
import Control.Monad (forM_)

main = do
    h <- J.new :: IO (J.JudyL Int)
    forM_ [0..10000000] $ \i -> J.insert (fromIntegral i) i h
    v <- J.lookup 100 h
    putStrLn $ show v
Run Code Online (Sandbox Code Playgroud)

计时如上:

$ time ./Main
Just 100

real    0m0.958s
user    0m0.924s
sys     0m0.032s
Run Code Online (Sandbox Code Playgroud)

定时OP的python代码:

$ time ./main.py
100

real    0m1.067s
user    0m0.886s
sys     0m0.180s
Run Code Online (Sandbox Code Playgroud)


Chr*_*kle 8

hashtables"Cuckoo散列的注释文档,就像使用线性探测的基本哈希表实现一样,在调整表格大小时可能会遇到长时间的延迟".您使用new,它创建一个默认大小的新表.从查看源代码看,默认大小为2.插入10000000个项目可能需要多次调整.

尝试使用newSized.