避免“共享”的好方法?
假设有人将这个简单的 Python 代码翻译成 Haskell:
def important_astrological_calculation(digits):
# Get the first 1000000 digits of Pi!
lucky_numbers = calculate_first_digits_of_pi(1000000)
return digits in lucky_numbers
Haskell 版本:
importantAstrologicalCalculation digits =
isInfixOf digits luckyNumbers
where
luckyNumbers = calculateFirstDigitsOfPi 1000000
在使用 Haskell 版本之后,程序员惊讶地发现他的 Haskell 版本“泄漏”了内存——在第一次调用他的函数之后,luckyNumbers
永远不会被释放。这很麻烦,因为该程序包含一些更相似的函数,并且所有这些函数消耗的内存都很大。
有没有一种简单而优雅的方法可以让程序“忘记”luckyNumbers
?
Suppose that someone would translate this simple Python code to Haskell:
def important_astrological_calculation(digits):
# Get the first 1000000 digits of Pi!
lucky_numbers = calculate_first_digits_of_pi(1000000)
return digits in lucky_numbers
Haskell version:
importantAstrologicalCalculation digits =
isInfixOf digits luckyNumbers
where
luckyNumbers = calculateFirstDigitsOfPi 1000000
After working with the Haskell version, the programmer is astonished to discover that his Haskell version "leaks" memory - after the first time his function is called, luckyNumbers
never gets freed. That is troubling as the program includes some more similar functions and the memory consumed by all of them is significant.
Is there an easy and elegant way to make the program "forget" luckyNumbers
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在这种情况下,您的 pidigits 列表是一个常量(或“常量应用形式
),GHC 可能会将其浮出,计算一次,并在使用之间共享。如果没有对 CAF 的引用,它将被垃圾收集。
现在,一般来说,如果您想要重新计算某些内容,请将其转换为函数(例如通过添加虚拟
()
参数)并启用-fno-full-laziness
。有关 CAF 的链接问题中的示例:如何制作CAF 不是 Haskell 中的 CAF?In this case, your pidigits list is a constant (or "constant applicative form
), and GHC will probably float it out, calculate it once, and share amongst uses. If there are no references to the CAF, it will be garbage collected.
Now, in general, if you want something to be recalculated, turn it into a function (e.g. by adding a dummy
()
parameter) and enable-fno-full-laziness
. Examples in the linked question on CAFs: How to make a CAF not a CAF in Haskell?解决此问题的三种方法(基于此博文)
使用< code>INLINE pragmas
添加
{-# INLINE luckyNumbers #-}
和另一个importantAstrologicalCalculation
。这将使单独的调用彼此独立,每个调用都使用自己的
luckyNumbers
副本,该副本会迭代一次并立即由 GC 收集。优点:
缺点:
使用
-fno-full-laziness
GHC 标志用虚拟 lambda 包裹
luckyNumbers
并使用-fno-full-laziness< /code>:
如果没有该标志,GHC 可能会注意到
luckyNumbers
中的表达式不使用其参数,因此它可能会将其浮出并共享它。优点:
缺点:
-fno-full-laziness
功能化
Alonzo Church 著名地发现数据可以在函数中编码,我们可以使用它来避免创建可以共享的数据结构。
luckyNumbers
可以成为折叠 pi 数字的函数,而不是数据结构。优点:
缺点:
Three ways to solve this (based on this blog post)
Using
INLINE
pragmasAdd
{-# INLINE luckyNumbers #-}
and another forimportantAstrologicalCalculation
.This will make separate calls be independent from each other, each using their own copy of the
luckyNumbers
which is iterated once and is immediately collected by the GC.Pros:
Cons:
Using the
-fno-full-laziness
GHC flagWrap
luckyNumbers
with a dummy lambda and use-fno-full-laziness
:Without the flag, GHC may notice that the expression in
luckyNumbers
doesn't use its parameter and so it may float it out and share it.Pros:
Cons:
-fno-full-laziness
Functionalization
Alonzo Church famously discovered that data can be encoded in functions, and we can use it to avoid creating data structures that could be shared.
luckyNumbers
can be made to a function folding over the digits of pi rather than a data structure.Pros:
Cons: