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绑定到变量a和o.一旦进入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的存储.然而,这对我来说似乎有点矫枉过正.我在俯瞰什么?感谢您对我冗长的解释感到满意.
注意:我不一定要寻找代码答案,更多的建议,建议等.
您可以评估obj和actionssnaplet初始化,结果存储到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只会被评估一次.