我正在玩GHCI,并且遇到了这个小怪(对我来说)奇怪. 我试过这个: λ let fibs = 1 : 1 : zipWith (+) fibs (tail fibs)λ fibs 只是为了看看纤维是如何快速生长的,只是为了玩一下.我认为Haskell如何在计
我试过这个:
λ> let fibs = 1 : 1 : zipWith (+) fibs (tail fibs) λ> fibs
只是为了看看纤维是如何快速生长的,只是为了玩一下.我认为Haskell如何在计算时显示每个纤维很酷,所以这是一个很好的懒惰示范.
然而,当我看到数字墙放大时,有一些短暂的跳过,列表生成将完全停止.通常我会认为它是计算下一个数字,但它们似乎是随机发生的 – 计算下一个原始数字总是只有一个加法,所以永远不要慢.在一个数字上,ghci暂停了将近一秒钟.
是什么导致了这些短暂的减速?为什么他们只发生在特定的数字而不是其他数字?这不应该快吗?
这几乎可以肯定是垃圾收集(GC),可能是更高代(即主要GC).在创建大量长寿命垃圾的情况下,这些可能会导致严重的暂停.如果您希望看到这种情况发生,您可以快速执行并检查:
从tmp.hs开始:
module Main where fibs = 1:1:zipWith (+) fibs (tail fibs) main = print $fibs !! 100000
用ghc -rtsopts tmp.hs编译
使用./tmp RTS -s运行
454,847,088 bytes allocated in the heap 230,044,816 bytes copied during GC 4,291,856 bytes maximum residency (226 sample(s)) 18,080,904 bytes maximum slop 56 MB total memory in use (0 MB lost due to fragmentation) Tot time (elapsed) Avg pause Max pause Gen 0 676 colls, 0 par 0.07s 0.07s 0.0001s 0.0023s Gen 1 226 colls, 0 par 0.27s 0.28s 0.0012s 0.0084s INIT time 0.00s ( 0.00s elapsed) MUT time 0.14s ( 0.14s elapsed) GC time 0.34s ( 0.35s elapsed) EXIT time 0.00s ( 0.00s elapsed) Total time 0.48s ( 0.49s elapsed) %GC time 71.0% (71.6% elapsed) Alloc rate 3,303,664,644 bytes per MUT second Productivity 28.9% of total user, 28.8% of total elapsed
这意味着676个小型垃圾收集和226个主要收集,第二代收集所需的时间比未成年人少12倍.请注意,这只是第十万个数字,因此在较高数字时暂停可能会更长.另请注意,GHCI是一名翻译,所以会有相关的减速.
顺便说一句,我尝试编译并运行此示例并启用优化.时间上没有明显差异,记忆/ GC特征几乎相同.