- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我使用 haskell 进行基于行的数据处理,即可以应用的任务 sed
, awk
和类似的工具。作为一个简单的例子,让我们在前面加上 000
从标准输入到每一行。
我有三种替代方法来完成这项任务:
ByteString
小号 ByteString
内加工。 example.hs
:
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE FlexibleContexts #-}
import ClassyPrelude.Conduit
import qualified Data.ByteString.Char8 as B8
import qualified Data.ByteString.Lazy.Char8 as BL8
import qualified Data.Conduit.Binary as CB
main = do
[arg] <- getArgs
case arg of
"lazy" -> BL8.getContents >>= BL8.putStr . BL8.unlines . map ("000" ++) . BL8.lines
"lines" -> runConduitRes $ stdinC .| CB.lines .|
mapC ("000" ++) .| mapC (`snoc` 10) .| stdoutC
"chunks" -> runConduitRes $ stdinC .| lineChunksC .|
mapC (B8.unlines . (map ("000" ++)) . B8.lines) .| stdoutC
lineChunksC :: Monad m => Conduit ByteString m ByteString
lineChunksC = await >>= maybe (return ()) go
where
go acc = if
| Just (_, 10) <- unsnoc acc -> yield acc >> lineChunksC
| otherwise -> await >>= maybe (yield acc) (go' . breakAfterEOL)
where
go' (this, next) = let acc' = acc ++ this in if null next then go acc' else yield acc' >> go next
breakAfterEOL :: ByteString -> (ByteString, ByteString)
breakAfterEOL = uncurry (\x -> maybe (x, "") (first (snoc x)) . uncons) . break (== 10)
$ stack ghc --package={classy-prelude-conduit,conduit-extra} -- -O2 example.hs -o example$ for cmd in lazy lines chunks; do echo $cmd; time -p seq 10000000 | ./example $cmd > /dev/null; echo; donelazyreal 2.99user 3.06sys 0.07linesreal 3.30user 3.36sys 0.06chunksreal 1.83user 1.95sys 0.06
(The results are consistent across multiple runs, and also hold for lines with several numbers).
So chunks
is 1.6x faster than lines
which is a bit faster than lazy
. This means that conduits can be faster than plain bytestrings, but the overhead of conduit pipes is too heavy when you split chunks into short lines.
What I don't like about chunks
approach is that it mixes both conduit and pure worlds, and it makes it harder to use it for more complex tasks.
The question is, did I miss a simple and elegant solution which would allow me to write efficient code in same fashion as with lines
approach?
EDIT1: Per @Michael's suggestion I joined two mapC
into one mapC (("000" ++). (
snoc10))
in lines
solution, to make number of pipes (.|
) same between lines
and chunks
. This made it perform a bit better (down from 3.3s to 2.8s), but still significantly slower than chunks
.
Also I tried older Conduit.Binary.lines
which Michael suggested in comments, and it also improves performance a bit, by ~0.1s.
EDIT2: Fixed lineChunksC
so it works with very small chunks, e.g.
> runConduitPure $ yield ("\nr\n\n"::ByteString) .| concatC .| mapC singleton .| lineChunksC .| sinkList
["\n","r\n","\n"]
最佳答案
我的猜测是,对于“线条”,mapC ("000" ++) .| mapC (`snoc` 10)
部分正在做很多工作。
连接几个严格的ByteStrings
进入另一个严格的ByteString
太贵了。将它们连接成一个懒惰的 ByteString
往往更有效率。
为避免此成本,您可以将每个部分单独生成为严格的 ByteString
下游。 (但请注意,我们不再谈论“线条”)。
或者,将每个转换后的行作为惰性 ByteString
下游。
The question is, did I miss a simple and elegant solution which would allow me to write efficient code in same fashion as with lines approach?
Data.ByteString.Streaming.Char8
对于流式字节串,我们有
lines
功能:
lines :: Monad m => ByteString m r -> Stream (ByteString m) m r
lines turns a ByteString into a connected stream of ByteStrings at divide at newline characters. The resulting strings do not contain newlines. This is the genuinely streaming lines which only breaks chunks, and thus never increases the use of memory.
ByteString m r
已经是流媒体类型了!所以这个版本的
lines
将流转换为“流的流”。而我们只能通过耗尽“当前流”(当前行)到达“下一个流”(下一行)。
{-# language OverloadedStrings #-}
module Main where
import Control.Applicative ((*>))
import Streaming
import qualified Streaming.Prelude as S
import qualified Data.ByteString.Streaming.Char8 as Q
main :: IO ()
main = Q.stdout
. Q.unlines
. S.maps (\line -> "000" *> line)
. Q.lines
$ Q.stdin
关于haskell - 提高基于线路的导管性能的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40319710/
在典型的 TSP 算法中,我们有多个点,我们希望以最优的行进顺序行进。点是家庭、客户等,基本上是 map 上的一个点。 我有线来优化,而不是点。扫雪机就是一个很好的例子,您可以在多条街道上行驶。最大的
对于我的计算机视觉类(class),我将做一个项目,我将根据走廊的图像提取关于走廊的信息。特别是,向消失点延伸的走廊线会很有趣。我的问题是我是否应该使用 Matlab、OpenCV 或其他东西来实现这
是否有任何工具可以查看 HTTP 2.0 的传输情况(原始请求和响应)?我使用 Fiddler,只看到 HTTP 1.1 数据。 我在 Chrome 中启用了 HTTP 2.0/SPDY 并访问了 h
我们想对我们办公室的两条 ADSL 线路进行负载平衡。 我对 is 的经验有限,想知道是否有人可以为我提供理论之外的解决方案,换句话说,关于硬件和软件要求和建议的细节。 所以我们有 2 条 4mb A
Warning: Error in parsing value for 'display'. Declaration dropped. Line: 0 我不确定当我留下这个警告时会发生什么,因为我没有
我想知道这条 SDP 线的含义是什么,因为我正试图在 5% 到 10% 的数据包丢失情况下获得最平滑的帧速率。 我不知道的行是:a=rtcp-fb:100 goog-remba=rtcp-fb:100
出于某种原因,我在我的所有 CSS 文件中都收到了这个警告/错误,但我不太明白。当我通过 W3C Validator 运行我的 CSS 时结果 100% 有效且格式正确等。但是,在 Firefox 中
我是一名优秀的程序员,十分优秀!