- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
回想起来,整个问题可以归结为更简洁的东西。我正在寻找一个 Haskell 数据结构
import Data.Vector.Unboxed (Vector)
data PixelMap = RGB8 {
width :: Int
, height :: Int
, redChannel :: Vector Word8
, greenChannel :: Vector Word8
, blueChannel :: Vector Word8
}
import Data.Attoparsec.ByteString
data Progress = Progress {
addr :: Int
, size :: Int
, redC :: Vector Word8
, greenC :: Vector Word8
, blueC :: Vector Word8
}
parseColorBinary :: Progress -> Parser Progress
parseColorBinary progress@Progress{..}
| addr == size = return progress
| addr < size = do
!redV <- anyWord8
!greenV <- anyWord8
!blueV <- anyWord8
parseColorBinary progress { addr = addr + 1
, redC = redC V.// [(addr, redV)]
, greenC = greenC V.// [(addr, greenV)]
, blueC = blueC V.// [(addr, blueV)] }
Progress{..} <- parseColorBinary $ ...
return $ RGB8 width height redC greenC blueC
Progress
的定义这样
redC
,
greenC
, 和
blueC
都是
!(Vector Word8)
,然后程序保持在合理的内存范围内,但是加载单个文件需要很长时间,以至于我不允许它实际完成。最后,如果我用标准列表替换这里的向量,我的内存使用量会回升到每个文件 5GB(我假设......我实际上在点击之前用完了空间),加载时间大约为 6 秒. Ubuntu 的预览应用程序一旦启动,就会几乎立即加载和呈现文件。
Data.Vector.Unboxed.Mutable
,但是...我什至无法进行类型检查。文档不存在,理解数据类型在做什么也需要与多个其他库进行斗争。而且我什至不知道它是否能解决问题,所以我什至都不愿意尝试。
performance
分支包含一个严格版本的解析器,可以通过快速更改
Progress
使其成为非严格版本。
Codec.Image.Netpbm
的数据结构.
ulimit -Sv 6000000 -- set a ulimit of 6GB, or change to whatever makes sense for you
cabal build
dist/build/perf-test/perf-test +RTS -p -sstderr
最佳答案
我首先认为只需读取整个字节串,然后将内容解压缩到未装箱的向量中就足够了。实际上,即使没有神秘的空间泄漏,您发布的解析代码也会相当糟糕:您在输入的每个字节上复制所有三个向量的整体!谈论二次复杂度。
所以我写了以下内容:
chunksOf3 :: [a] -> [(a, a, a)]
chunksOf3 (a:b:c:xs) = (a, b, c) : chunksOf3 xs
chunksOf3 _ = []
parseRGB :: Int -> Atto.Parser (Vector Word8, Vector Word8, Vector Word8)
parseRGB size = do
input <- Atto.take (size * 3)
let (rs, gs, bs) = unzip3 $ chunksOf3 $ B.unpack input
return (V.fromList rs, V.fromList gs, V.fromList bs)
import Data.Vector.Unboxed (Vector)
import Data.ByteString (ByteString)
import qualified Data.Vector.Unboxed as V
import qualified Data.ByteString as B
import qualified Data.Vector.Unboxed.Mutable as MV
import Control.Monad.ST.Strict
import Data.Word
import Control.Monad
import Control.DeepSeq
-- benchmarking stuff
import Criterion.Main (defaultMainWith, bench, whnfIO)
import Criterion.Config (defaultConfig, Config(..), ljust)
-- This is just the part that parses the three vectors for the colors.
-- Of course, you can embed this into an Attoparsec computation by taking
-- the current input, feeding it to parseRGB, or you can just take the right
-- sized chunk in the parser and omit the "Maybe" test from the code below.
parseRGB :: Int -> ByteString -> Maybe (Vector Word8, Vector Word8, Vector Word8)
parseRGB size input
| 3* size > B.length input = Nothing
| otherwise = Just $ runST $ do
-- We are allocating three mutable vectors of size "size"
-- This is usually a bit of pain for new users, because we have to
-- specify the correct type somewhere, and it's not an exactly simple type.
-- In the ST monad there is always an "s" type parameter that labels the
-- state of the action. A type of "ST s something" is a bit similar to
-- "IO something", except that the inner type often also contains "s" as
-- parameter. The purpose of that "s" is to statically disallow mutable
-- variables from escaping the ST action.
[r, g, b] <- replicateM 3 $ MV.new size :: ST s [MV.MVector s Word8]
-- forM_ = flip mapM_
-- In ST code forM_ is a nicer looking approximation of the usual
-- imperative loop.
forM_ [0..size - 1] $ \i -> do
let i' = 3 * i
MV.unsafeWrite r i (B.index input $ i' )
MV.unsafeWrite g i (B.index input $ i' + 1)
MV.unsafeWrite b i (B.index input $ i' + 2)
-- freeze converts a mutable vector living in the ST monad into
-- a regular vector, which can be then returned from the action
-- since its type no longer depends on that pesky "s".
-- unsafeFreeze does the conversion in place without copying.
-- This implies that the original mutable vector should not be used after
-- unsafeFreezing.
[r, g, b] <- mapM V.unsafeFreeze [r, g, b]
return (r, g, b)
-- I prepared a file with 3 * 15 million random bytes.
inputSize = 15000000
benchConf = defaultConfig {cfgSamples = ljust 10}
main = do
defaultMainWith benchConf (return ()) $ [
bench "parseRGB test" $ whnfIO $ do
input <- B.readFile "randomInp.dat"
force (parseRGB inputSize input) `seq` putStrLn "done"
]
关于performance - 如何在 Haskell 中将大数据 block 解析到内存中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22525250/
我的 blockly.js 文件中有以下代码 Blockly.Blocks['account_number'] = { // Other type. init: function() {
首先抱歉我的英语不好,我正在开发 Image Splitter 应用程序并且已经完成,但是现在的要求是当图像被分割(分成几 block /chunks)那么图像 block 的每一 block (ch
#value: 消息的返回值,当发送到一个 block 时,是该 block 中最后一句话的值。所以 [ 1 + 2. 3 + 4. ] value 计算结果为 7。我发现有时很难使用。有没有办法显式
我想构建一个包含 3 div 的响应式导航栏相同的 width和 height . 我申请了 inline-block到每个 block ,我得到一个我不理解的行为。 问题是,第三 block 由 2
我希望使用 Blockly 来允许非技术人员用户指定测试脚本。 它的一部分需要一个文件选择器,但是,我看不到 Blockly 有一个。是吗? 实际上,我找不到完整的标准 block 列表。谁有网址?
仅当您位于父 block 内部时,父 block 的 props.isSelected 才为 true,但当您在该 block 的 innerBlocks 内进行编辑时则不然。 如何从父 block
仅当您位于父 block 内部时,父 block 的 props.isSelected 才为 true,但当您在该 block 的 innerBlocks 内进行编辑时则不然。 如何从父 block
我想创建一个具有不同背景颜色 block 和不同悬停颜色 block 的导航栏 block 。我可以分别创建不同的悬停颜色 block 或不同的背景颜色 block ,但不能一起创建。所以请告诉我如何
我正在使用看到的代码 here定期执行代码: #define DELAY_IN_MS 1000 __block dispatch_time_t next = dispatch_time(DISPATC
为什么 block 必须被复制而不是保留?两者在引擎盖下有什么区别?在什么情况下不需要复制 block (如果有)? 最佳答案 通常,当您分配一个类的实例时,它会进入堆并一直存在,直到它被释放。但是,
我想弄清楚我这样做是否正确: 如果我有一个 block ,我会这样做: __weak MyClass *weakSelf = self; [self performBlock:^{
我想制作一个 4 block 导航菜单,虽然我已经显示了一个 block ,然后单击打开第二个 block ,从第二个开始选择并再次单击出现第三个 block ,第四个 block 相同...这是我的
例如,这样更好吗? try { synchronized (bean) { // Write something } } catch (Int
我想让一只乌龟检查前方小块的颜色并决定移动到哪里。如果前面的补丁不是白色的,那么乌龟向左或向右旋转并移动。我的 If 决策结构中出现错误,显示“此处应为 TRUE?FALSE,而不是 block 列表
我想创建一个 block 对角矩阵,其中对角 block 重复一定次数,非对角 block 都是零矩阵。例如,假设我们从一个矩阵开始: > diag.matrix [,1] [,2] [
我是区 block 链新手。突然我有一个问题,我们是否可以通过区 block 号来访问以太坊区 block 链上之前的区 block 数据。 例如我创建了一个block1、block2。 block
我是区 block 链新手。突然我有一个问题,我们是否可以通过区 block 号来访问以太坊区 block 链上之前的区 block 数据。 例如我创建了一个block1、block2。 block
我创建了一个等距环境,全部使用 Javascript 和 HTML5 (2D Canvas),大部分情况下工作正常。我面临的问题是使用不同高度的图 block ,然后对图 block 上的对象索引进行
这是令我困惑的代码: public Integer getInteger(BlockingQueue queue) { boolean interrupted = false; try
我有一个基于 TPL 数据流的应用程序,它仅使用批处理 block 和操作 block 就可以正常工作。 我已经添加了一个 TransformBlock 以尝试在发布到批处理 block 之前从源中转
我是一名优秀的程序员,十分优秀!