受这个 StackOverflow 问题的启发,我想向社区询问有关Binary
. 当我注意到我的大型Hyperedge
s 列表(一个简单的代数数据结构)不会被流式传输而是立即加载时,我编写了使用 10000 个元素块的myGet
andmyPut
函数。如上述 StackOverflow 问题的答案所述,我的实现不适用于 Binary >= 0.5。(我错过了。)
但是,我还注意到,在将Hyperedge
s 与Int
它们Int32
的类型参数一起加载时,很多Word32
s 和Word64
s 被分配只是为了稍后转换。那是一次巨大的空间泄漏。deepseq
如您所见,我get
尽可能早地“修复”了它。我本来希望使用更精致的方法,也许使用Strategy
,但话又说回来,我不能再使用Binary
类型类了,因为该策略必须是一个附加参数。
总结:现在,一团糟。你能提供“最佳实践”的建议吗?
instance (NFData v, NFData l, NFData i, B.Binary v, B.Binary l, B.Binary i, Ord v)
=> B.Binary (Hyperedge v l i) where
put e = do
B.put (to e)
B.put (from e)
B.put (label e)
B.put (ident e)
-- get = mkHyperedge <$> B.get <*> B.get <*> B.get <*> B.get
get = do
x1 <- B.get
x2 <- x1 `deepseq` B.get
x3 <- x2 `deepseq` B.get
x4 <- x3 `deepseq` B.get
x4 `deepseq` return (mkHyperedge x1 x2 x3 x4)
myGet
:: (NFData v, NFData l, NFData i, B.Binary v, B.Binary l, B.Binary i, Ord v)
=> B.Get [Hyperedge v l i]
myGet = do
es1 <- B.get
if null es1
then return []
else
do
es2 <- myGet
return (es1 ++ es2)
myPut
:: (NFData v, NFData l, NFData i, B.Binary v, B.Binary l, B.Binary i, Ord v)
=> [Hyperedge v l i] -> B.Put
myPut es@[] = B.put es -- ([] :: [Hyperedge v l i])
myPut es = do
B.put (take 10000 es)
myPut (drop 10000 es)