我已用Haskell编写了一个软实时应用程序,处理模拟物理、碰撞检测等功能。在这个过程中,我使用了大量的内存,如果需要的话,我可以优化我的内存使用。但是,由于我目前的CPU利用率为40%,只使用了1%的RAM,所以似乎没有必要。不过问题在于,当垃圾回收器开始工作时,很多时候都会出现跳帧的情况。通过使用
threadscope
进行性能分析后,我证实了这是问题的根本原因:在执行有用计算之前,垃圾回收器偶尔需要长达0.05秒的时间,导致最多跳过3帧,这非常明显和非常恼人。
现在,我尝试通过每一帧手动调用performMinorGC
来解决这个问题,这似乎缓解了这个问题,使它变得更加平滑,但总体CPU使用率急剧上升到70%左右。显然,我宁愿避免这种情况。
我尝试的另一件事是,将GC的分配空间从512k减少到64k,并尝试设置-I0.03以尽可能频繁地进行回收。这两个选项都改变了我在threadscope
中看到的垃圾收集模式,但仍导致跳帧。
有经验的GC优化人士能帮我解决这个问题吗?我是否注定要手动调用performMinorGC
并忍受由此产生的巨大性能损失?
编辑
我尝试在这些测试中运行了相似数量的时间,但因为它是实时的,所以没有任何时刻是“完成”的。
每4帧使用performMinorGC
的运行时统计信息:
9,776,109,768 bytes allocated in the heap
349,349,800 bytes copied during GC
53,547,152 bytes maximum residency (14 sample(s))
12,123,104 bytes maximum slop
105 MB total memory in use (0 MB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause
Gen 0 15536 colls, 15536 par 3.033s 0.997s 0.0001s 0.0192s
Gen 1 14 colls, 13 par 0.207s 0.128s 0.0092s 0.0305s
Parallel GC work balance: 6.15% (serial 0%, perfect 100%)
TASKS: 20 (2 bound, 13 peak workers (18 total), using -N4)
SPARKS: 74772 (20785 converted, 0 overflowed, 0 dud, 38422 GC'd, 15565 fizzled)
INIT time 0.000s ( 0.001s elapsed)
MUT time 9.773s ( 7.368s elapsed)
GC time 3.240s ( 1.126s elapsed)
EXIT time 0.003s ( 0.004s elapsed)
Total time 13.040s ( 8.499s elapsed)
Alloc rate 1,000,283,400 bytes per MUT second
Productivity 75.2% of total user, 115.3% of total elapsed
gc_alloc_block_sync: 29843
whitehole_spin: 0
gen[0].sync: 11
gen[1].sync: 71
没有performMinorGC
12,316,488,144 bytes allocated in the heap
447,495,936 bytes copied during GC
63,556,272 bytes maximum residency (15 sample(s))
15,418,296 bytes maximum slop
146 MB total memory in use (0 MB lost due to fragmentation)
Tot time (elapsed) Avg pause Max pause
Gen 0 19292 colls, 19292 par 2.613s 0.950s 0.0000s 0.0161s
Gen 1 15 colls, 14 par 0.237s 0.165s 0.0110s 0.0499s
Parallel GC work balance: 2.67% (serial 0%, perfect 100%)
TASKS: 17 (2 bound, 13 peak workers (15 total), using -N4)
SPARKS: 100714 (29688 converted, 0 overflowed, 0 dud, 47577 GC'd, 23449 fizzled)
INIT time 0.000s ( 0.001s elapsed)
MUT time 13.377s ( 9.917s elapsed)
GC time 2.850s ( 1.115s elapsed)
EXIT time 0.000s ( 0.006s elapsed)
Total time 16.247s ( 11.039s elapsed)
Alloc rate 920,744,995 bytes per MUT second
Productivity 82.5% of total user, 121.4% of total elapsed
gc_alloc_block_sync: 68533
whitehole_spin: 0
gen[0].sync: 9
gen[1].sync: 147
由于某种原因,与我昨天测试时相比,现在没有使用performMinorGC
的总体生产力似乎更低了——以前总是大于90%。
+RTS -s
)。 - Yuras