- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我发现了一个库的一小部分似乎包含内存泄漏。下面的代码尽可能小,但仍然产生与真实代码相同的结果。
import System.Random
import Control.Monad.State
import Control.Monad.Loops
import Control.DeepSeq
import Data.Int (Int64)
import qualified Data.Vector.Unboxed as U
vecLen = 2048
main = flip evalStateT (mkStdGen 13) $ do
let k = 64
cs <- replicateM k transform
let sizeCs = k*2*7*vecLen*8 -- 64 samples, 2 elts per list, each of len 7*vecLen, 8 bytes per Int64
(force cs) `seq` lift $ putStr $ "Expected to use ~ " ++ (show ((fromIntegral sizeCs) / 1000000 :: Double)) ++ " MB of memory\n"
transform :: (Monad m, RandomGen g)
=> StateT g m [U.Vector Int64]
transform = do
e <- liftM ((U.map round) . (uncurry (U.++)) . U.unzip) $ U.replicateM (vecLen `div` 2) sample
c1 <- U.replicateM (7*vecLen) $ state random
return [U.concat $ replicate 7 e, c1]
sample :: (RandomGen g, Monad m) => StateT g m (Double, Double)
sample = do
let genUVs = liftM2 (,) (state $ randomR (-1,1)) (state $ randomR (-1,1))
-- memory usage drops and productivity increases to about 58% if I set the guard to "False" (the real code needs a guard here)
uvGuard (u,v) = u+v >= 2 -- False --
(u,v) <- iterateWhile uvGuard genUVs
return (u, v)
删除更多代码可以显着提高性能,无论是在内存使用/GC、时间还是两者方面。但是,我需要计算上面的代码,所以真正的代码再简单不过了。例如,如果我让 e 和 c1 都从 sample
获取值,则代码使用 27 MB 内存,并在 GC 中花费 9% 的运行时间。如果我让 e 和 c1 都使用状态随机
,我会使用大约 400MB 的内存,并且只在 GC 上花费 32% 的运行时间。
主要参数是vecLen
,我确实需要8192左右。为了加快分析速度,我用vecLen=2048
生成了下面的所有结果,但问题是随着 vecLen
的增加,情况会变得更糟。
编译
ghc test -rtsopts
我得到:
> ./test +RTS -sstderr
Working...
Expected to use ~ 14.680064 MB of memory
Done
3,961,219,208 bytes allocated in the heap
2,409,953,720 bytes copied during GC
383,698,504 bytes maximum residency (17 sample(s))
3,214,456 bytes maximum slop
869 MB total memory in use (0 MB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause
Gen 0 7002 colls, 0 par 1.33s 1.32s 0.0002s 0.0034s
Gen 1 17 colls, 0 par 1.60s 1.84s 0.1080s 0.5426s
INIT time 0.00s ( 0.00s elapsed)
MUT time 2.08s ( 2.12s elapsed)
GC time 2.93s ( 3.16s elapsed)
EXIT time 0.00s ( 0.03s elapsed)
Total time 5.01s ( 5.30s elapsed)
%GC time 58.5% (59.5% elapsed)
Alloc rate 1,904,312,376 bytes per MUT second
Productivity 41.5% of total user, 39.2% of total elapsed
real 0m5.306s
user 0m5.008s
sys 0m0.252s
使用 -p 或 -h* 进行分析并不能透露太多信息,至少对我来说是这样。
但是,线程作用域很有趣:
在我看来,我好像在破坏堆,所以 GC 正在发生,堆大小加倍。事实上,当我使用 -H4000M 运行时,threadscope 看起来稍微更均匀(更少的双倍工作,双倍 GC),但我仍然花费大约 60% 的总体运行时间来执行 GC。使用 -O2 编译情况更糟,超过 70% 的运行时间都花在 GC 上。
问题:1. 为什么GC运行这么多?2. 我的堆使用量是否出乎意料地大?如果是这样,为什么?
对于问题 2,我意识到堆使用量可能会超出我的“预期”内存使用量,甚至超出很多。但800MB对我来说似乎有点太大了。 (这就是我应该查看的数字吗?)
最佳答案
为了解决这样的问题,我通常会在我认为可能有大量分配的地方使用 SCC
编译指示来开始代码。在这种情况下,我怀疑 transform
中的 e
和 c1
以及 sample< 中的
,genUVs
/
...
transform :: (Monad m, RandomGen g)
=> StateT g m [U.Vector Int64]
transform = do
e <- {-# SCC e #-} liftM (U.map round . uncurry (U.++) . U.unzip) $ U.replicateM (vecLen `div` 2) sample
c1 <- {-# SCC c1 #-} U.replicateM (7*vecLen) $ state random
return [U.concat $ replicate 7 e, c1]
sample :: (RandomGen g, Monad m) => StateT g m (Double, Double)
sample = do
let genUVs = {-# SCC genUVs #-} liftM2 (,) (state $ randomR (-1,1)) (state $ randomR (-1,1))
-- memory usage drops and productivity increases to about 58% if I set the guard to "False" (the real code needs a guard here)
uvGuard (u,v) = u+v >= 2 -- False --
(u,v) <- iterateWhile uvGuard genUVs
return $ (u, v)
我们首先使用 -hy
查看相关对象的类型。这揭示了许多不同的类型,包括Integer
、Int32
、StdGen
、Int
和(, )
。使用-hc
我们可以确定几乎所有这些值都分配在transform
的c1
中。 -hr
证实了这一点,它告诉我们谁持有对这些对象的引用(从而防止它们被垃圾收集)。我们可以通过使用 -hrc1 -hy
检查它保留的对象类型来进一步确认 c1
是罪魁祸首(假设我们用 {-# 注解它) SCC c1 #-}
)。
事实上,c1
保留了如此多的对象,这表明它没有在我们希望的时候被评估。虽然在评估之后,c1
是一个相当短的向量,但在评估之前,它需要数千个随机种子、关联的闭包,以及可能的许多其他对象。
Deepseq
ing c1
使 GC 时间从 59% 减少到 23%,并将内存消耗减少一个数量级。这就是 transform
中的终端 return
转变成,
deepseq c1 $ return [U.concat $ replicate 7 e, c1]
此后,配置文件看起来相当合理,最大的空间用户在 transform
中分配了大约 10MB 的 ARR_WORDS
(如预期),后面是一些元组,可能来自 genUVs
.
关于haskell - 过多的垃圾收集(和内存使用?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19164151/
我是 C 新手,还没有真正掌握 C 何时决定释放对象以及何时决定保留对象。 heap_t 是指向结构堆的指针。 heap_t create_heap(){ heap_t h_t = (heap
我有一个问题,我不知道如何解决。问题是: char * ary = new Char[]; ifstream fle; fle.open(1.txt, ios_base::binary); fle.s
假设我在 C# 中有字符串:“我看不到你……” 我想删除(替换为空等)这些“’”符号。 我该怎么做? 最佳答案 那个“垃圾”看起来很像有人将 UTF-8 数据解释为 ISO 8859-1 或 Wi
我无法在解析方法中更改蜘蛛设置。但这绝对是一种方式。 例如: class SomeSpider(BaseSpider): name = 'mySpider' allowed_domains
在开始之前,我们先回顾一下堆是个什么玩意,大家可能都知道,我们每天创建的Java对象几乎都存放在堆上面,所以说堆是一个巨大的对象池一点都不过分,在这个对象池里面管理者数据巨大的对象实例。 在对
我想知道为什么 printf() 在提供数组且没有格式化选项时成功打印字符数组,但在使用整数数组时编译器会抛出警告并打印垃圾值。 这是我的代码: #include int main() { c
我正在研究 Scrapy 库并尝试制作一个小爬虫。 这是爬虫的规则: rules = ( Rule(LinkExtractor(restrict_xpaths='//div[@class="w
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: Printing a string to a temporary stream object in C++
这个问题在这里已经有了答案: Are WebGL objects garbage collected? (2 个答案) 关闭 3 年前。 在 WebGL 中,纹理的创建和销毁使用: WebGLTex
我继承了以下代码: (为保护无辜者更改了一些名称。) package foo.bar.baz; import javax.swing.JPanel; //Main panel in the GUI c
如果我没记错的话,在某些情况下,Java 中的 lambda 会生成为匿名类实例。例如,在这段代码中,lambda 需要从外部捕获一个变量: final int local = 123456; lis
我正在阅读托管代码中的内存泄漏,想知道是否可以在 C# 不安全代码中创建它? unsafe { while(true) new int; } 我不确定如果它作为不安全代码运行,是否会被 GC
假设我有以下用 HTML 编写的网页(仅正文部分): ... function fn() { // do stu
我想知道是否有简单的命令可以删除在 latex 编译过程中生成的所有不必要的文件,例如.aux、.log 等 最好将它链接到常规的 Latex 构建命令,这样在我点击“编译”后,垃圾文件就会被删除。
Java 在 Java7 中引入了带有字符串的 switch case。我想知道使用这样的开关盒是否会产生垃圾。 例如在我的程序中, String s = getString(); switch(s)
Cevelop将 char junk 作为“未初始化的变量”对象。在这种情况下,解决问题的正确方法是什么? friend std::ostream& operator>(std::istream&
关闭。这个问题需要debugging details .它目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and t
我正在编写一个发送和接收纯文本的小型 boost asio tcp 服务器和客户端。通信或多或少是请求响应。在测试期间,我想我只是向服务器发送垃圾数据,向它发送 100.000 个请求。 客户端发
我正在使用 SAX 来读取/解析 XML 文档,并且它工作正常,除了这个特定的站点,在该站点中 eclipse 告诉我“文档元素之后的垃圾”并且我没有返回任何数据 http://www.zachblu
这是我的 Scrapy 爬虫代码。我正在尝试从网站中提取元数据值。没有元数据在一个页面上出现多次。 class MySpider(BaseSpider): name = "courses"
我是一名优秀的程序员,十分优秀!