在内存中"保存"数据映射

eaz*_*001 2 multithreading haskell memory-management haskell-snap-framework

我有三个数据结构定义为这样的,其中S,LL,M,和Object,表示Set,ListLike,Map,和ByteString,分别为:

nouns :: IO [Object]
nouns = liftM LL.words $ B.readFile "nounlist.txt"

obj :: IO ObjectSet
obj =  liftM S.fromList nouns

actions :: IO ActionMap
actions = do
  n <- nouns
  let l = foldl' (\z x -> (x,Sell):(x,Create):z) [] n
  return $ M.fromList $
    (\(x,y) -> ((x, Verb y []), Out (Verb y []) x)) <$> l
Run Code Online (Sandbox Code Playgroud)

现在我有一个函数将未评估的Set和Map绑定到变量ao.一旦进入query,通过用户输入接受并处理无限循环的查询.通过查找生成适当的响应.

process :: IO ()
process = do
  a <- actions
  o <- obj
  forever $ query "" a o
Run Code Online (Sandbox Code Playgroud)

请记住,我的Map由300,000多个键值对组成:在我的计算机上调用第一个查询时,第一次评估的初始时间开销大约在3-5秒之间.这很好,完全可以预料到.其他所有后续电话都是快速响应的,就像我想要的那样.然而,这仅仅是如此,因为我运行此代码作为独立的可执行文件,并有内住的奢侈IO ()process.如果我将这个代码(以及未列出的其余代码)转换成一个库来与一个Snap Framework Web应用程序接口,我不一定会有这种奢侈.基本上我想说的是:如果我要删除forever,process那么评估的Map和Set肯定会被垃圾收集.实际上,当我从Snap应用程序调用该函数时会发生这种情况(我无法保留,forever因为它会阻止Snap应用程序).来自Snap应用程序的每个后续调用都将具有相同的3-5秒开销,因为它会重新评估相关数据结构.


我的问题:

有没有一种简单的方法可以将Map和Set保存在内存中,以便每次后续查找都很快?我想出的一个想法是运行一个线程来休眠并维护Map和Set的存储.然而,这对我来说似乎有点矫枉过正.我在俯瞰什么?感谢您对我冗长的解释感到满意.

注意:我不一定要寻找代码答案,更多的建议,建议等.

max*_*kin 7

您可以评估objactionssnaplet初始化,结果存储到snaplet的状态中只有一次.

data SnapApp = SnapApp
    { objectSet :: ObjectSet
    , actionMap :: ActionMap
    }

appInit :: SnapletInit SnapApp SnapApp
appInit = makeSnaplet ... $ do
    ... 
    a <- liftIO actions
    o <- liftIO obj
    return $ SnapApp o a
Run Code Online (Sandbox Code Playgroud)

现在您可以从快照中访问它们Handler:

someUrlHandler :: Handler SnapApp SnapApp
someUrlHandler = do
  a <- gets actionMap
  o <- gets objectMap
  res <- query a o
  ...
Run Code Online (Sandbox Code Playgroud)

这保证了actions并且obj只会被评估一次.