如何在恒定空间中使用monadic动作折叠惰性列表?我试图解决的问题是聚合一个大文件,我相信为了性能我需要可变性.我有一个使用可变向量在ST工作的实现,但它使用了太多的内存.以下是我正在尝试的一个例子.我还对Conduit进行了简要的实验,但似乎没有提供任何改进.
ST forM_:
import Control.Monad (forM_)
import Control.Monad.ST.Trans as STT
import Control.Monad.Identity as Identity
testST :: Int
testST = do
Identity.runIdentity $ STT.runST $ do
a <- STT.newSTRef 0
forM_ [1..10000000] (\x -> do
a' <- STT.readSTRef a
STT.writeSTRef a (a' + x)
)
STT.readSTRef a
Run Code Online (Sandbox Code Playgroud)
导管:
import Data.Conduit (($=),(=$),($$))
import qualified Data.Conduit as C
import qualified Data.Conduit.List as CL
testCL :: IO Int
testCL = CL.sourceList [1..10000000] $$ CL.foldM (\a x -> return (a + x)) 0
Run Code Online (Sandbox Code Playgroud) 如何将转换[Either ST]为a Either [ST]并随后依次运行操作?以下代码似乎适用于运行ST操作列表,但是当尝试在Either中生成操作列表(交换test下面的定义)时,类型不再排列.我本来期望列表的类型是相同的,所以我非常感谢对这些差异的任何解释.
{-# LANGUAGE RankNTypes #-}
import qualified Data.STRef as ST
import qualified Control.Monad.ST as ST
run :: (forall s. [ST.STRef s Int -> ST.ST s Int]) -> Int
run fs =
ST.runST $ do
x <- ST.newSTRef 0
mapM_ (\f ->
f x >>= ST.writeSTRef x
) fs
ST.readSTRef x
action :: ST.STRef s Int -> ST.ST s Int
action = \x -> ST.readSTRef x >>= \y -> return (y + 1) …Run Code Online (Sandbox Code Playgroud) 原版的
我正在尝试聚合CSV文件并体验[我认为的]过多的内存使用和/或GC工作.当群体数量增加时,似乎会出现这个问题.当密钥数百或数千时,没有问题,但当密钥达到数万时,很快就会开始在GC中花费大部分时间.
更新
移动Data.ByteString.Lazy.ByteString到Data.ByteString.Short.ShortByteString显著减少内存消耗(的水平,我认为是合理的).但是,在GC中花费的时间似乎仍远高于我预期的必要时间.我从感动Data.HashMap.Strict.HashMap到Data.HashTable.ST.Basic.HashTable,看是否在突变ST会帮助,但并没有出现.以下是当前的完整测试代码,包括generateFile创建测试样本:
{-# LANGUAGE OverloadedStrings #-}
module Main where
import System.IO (withFile, IOMode(WriteMode))
import qualified System.Random as Random
import qualified Data.ByteString.Short as BSS
import qualified Data.ByteString.Lazy.Char8 as BL
import qualified Data.Vector as V
import qualified Data.Vector.Mutable as MV
import qualified Control.Monad.ST as ST
import qualified Data.HashTable.ST.Basic as HT
import qualified Data.HashTable.Class as HT (toList)
import Data.Hashable (Hashable, hashWithSalt)
import Data.List (unfoldr)
import qualified Data.Traversable as T …Run Code Online (Sandbox Code Playgroud) 我曾尝试使用此Dockerfile构建在Google App Engine中运行的PoC Happstack可执行文件:
FROM ubuntu:14.04
ENV APP_ROOT=/usr/share/app
RUN apt-get update && apt-get install curl -y && curl -sSL https://get.haskellstack.org/ | sh
COPY . ${APP_ROOT}/
WORKDIR ${APP_ROOT}/
RUN stack setup
RUN stack build
EXPOSE 8000
ENTRYPOINT ["stack","exec","app-exe"]
Run Code Online (Sandbox Code Playgroud)
这工作,我能够部署,但结果图像似乎很大.
我认为安装后图像大约为450MB stack,大约1.8GB以下stack setup,大约3GB stack build.
我认为数百MB似乎合理,甚至高达GB.我应该采取不同的方法,也许将生成的可执行文件以某种方式提取到另一个图像,以消除运行时不必要的一切?