【问题标题】:Optimize Haskell GC usage优化 Haskell GC 使用
【发布时间】:2015-03-16 15:47:30
【问题描述】:

我正在运行一个长期存在的 Haskell 程序,该程序会占用大量内存。使用+RTS -N5 -s -A25M(我的 L3 缓存大小)运行,我看到了:

715,584,711,208 bytes allocated in the heap
390,936,909,408 bytes copied during GC
  4,731,021,848 bytes maximum residency (745 sample(s))
     76,081,048 bytes maximum slop
           7146 MB total memory in use (0 MB lost due to fragmentation)

                                  Tot time (elapsed)  Avg pause  Max pause
Gen  0     24103 colls, 24103 par   240.99s   104.44s     0.0043s    0.0603s
Gen  1       745 colls,   744 par   2820.18s   619.27s     0.8312s    1.3200s

Parallel GC work balance: 50.36% (serial 0%, perfect 100%)

TASKS: 18 (1 bound, 17 peak workers (17 total), using -N5)

SPARKS: 1295 (1274 converted, 0 overflowed, 0 dud, 0 GC'd, 21 fizzled)

INIT    time    0.00s  (  0.00s elapsed)
MUT     time  475.11s  (454.19s elapsed)
GC      time  3061.18s  (723.71s elapsed)
EXIT    time    0.27s  (  0.50s elapsed)
Total   time  3536.57s  (1178.41s elapsed)

Alloc rate    1,506,148,218 bytes per MUT second

Productivity  13.4% of total user, 40.3% of total elapsed

GC 时间占总运行时间的 87%!我在具有大量 RAM 的系统上运行它,但是当我设置较高的 -H 值时,性能会更差。

似乎-H-A 都控制gen 0 的大小,但我真正想做的是增加gen 1 的大小。最好的方法是什么?

【问题讨论】:

  • 这通常发生在很多东西不必要地在苗圃一代中幸存下来,从而使收集它们变得更加昂贵。我要检查的第一件事是空间泄漏,防止立即收集短期值。
  • 相关(那里的答案可能对您有帮助,也可能对您没有帮助,具体取决于您的情况):stackoverflow.com/questions/27630833/…
  • 首先获取堆配置文件。例如stackoverflow.com/a/3276557/83805
  • 这仍然相关吗?你有重现这种行为的程序吗?
  • 你能发布一个重现这个问题的程序吗?

标签: haskell memory-management garbage-collection profiling


【解决方案1】:

正如 Carl 建议的那样,您应该检查代码是否存在空间泄漏。我假设您的程序确实需要大量内存是有充分理由的。

该程序花费了 2820.18 秒进行主要 GC。您可以通过减少内存使用量(不是假设的情况)或主要集合的数量来降低它。你有很多空闲内存,可以试试-Ffactoroption

 -Ffactor

    [Default: 2] This option controls the amount of memory reserved for
 the older generations (and in the case of a two space collector the size
 of the allocation area) as a factor of the amount of live data. For
 example, if there was 2M of live data in the oldest generation when we
 last collected it, then by default we'll wait until it grows to 4M before
 collecting it again.

在您的情况下,大约有 3G 的实时数据。默认情况下,当堆增长到 6G 时将触发主要 GC。使用-F3,它将在堆增长到 9G 时触发,为您节省大约 1000 秒的 CPU 时间。

如果大多数实时数据是静态的(例如从不更改或更改缓慢),那么您将对stable heap 感兴趣。这个想法是从主要 GC 中排除长期存在的数据。它可以实现,例如使用compact normal forms,虽然它是not merged 进入GHC。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-30
    • 2019-07-03
    • 2019-05-17
    • 1970-01-01
    相关资源
    最近更新 更多