递归序列会泄漏内存吗? [英] Do recursive sequences leak memory?

查看:69
本文介绍了递归序列会泄漏内存吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我喜欢递归地定义序列,如下所示:

I like to define sequences recursively as follows:

let rec startFrom x =
    seq {
        yield x;
        yield! startFrom (x + 1)
    }

我不确定在实践中是否应该使用像这样的递归序列. yield! 似乎是尾递归的,但是我不确定它是100%可靠的,因为它是从另一个IEnumerable内部调用的.从我的角度来看,该代码在每次调用时都创建了IEnumerable的实例而不关闭它,这实际上也会使此函数泄漏内存.

I'm not sure if recursive sequences like this should be used in practice. The yield! appears to be tail recursive, but I'm not 100% sure since its being called from inside another IEnumerable. From my point of view, the code creates an instance of IEnumerable on each call without closing it, which would actually make this function leak memory as well.

此功能会泄漏内存吗?为此,它甚至是尾递归"吗?

:我正在摸索NProf寻求答案,但是我认为获得关于在SO上实现递归序列的技术解释会很有帮助.

: I'm fumbling around with NProf for an answer, but I think it would be helpful to get a technical explanation regarding the implementation of recursive sequences on SO.

推荐答案

我现在正在工作,所以我正在查看比Beta1稍新的位,但是在发布模式下的我的盒子上,然后使用.Net Reflector,看来这两个

I'm at work now so I'm looking at slightly newer bits than Beta1, but on my box in Release mode and then looking at the compiled code with .Net Reflector, it appears that these two

let rec startFromA x =    
    seq {        
        yield x     
        yield! startFromA (x + 1)    
    }

let startFromB x =    
    let z = ref x
    seq {        
        while true do
            yield !z
            incr z
    }

在发布"模式下编译时,

生成几乎相同的MSIL代码.它们的运行速度与此C#代码大致相同:

generate almost identical MSIL code when compiled in 'Release' mode. And they run at about the same speed as this C# code:

public class CSharpExample
{
    public static IEnumerable<int> StartFrom(int x)
    {
        while (true)
        {
            yield return x;
            x++;
        }
    }
}

(例如,我在包装盒上运行了所有三个版本,并打印了百万分之一的结果,每个版本大约需要1.3秒,+/-1秒). (我没有进行任何内存分析;可能我缺少了一些重要的东西.)

(e.g. I ran all three versions on my box and printed the millionth result, and each version took about 1.3s, +/- 1s). (I did not do any memory profiling; it's possible I'm missing something important.)

简而言之,除非您衡量并发现问题,否则我不会过多思考此类问题.

In short, I would not sweat too much thinking about issues like this unless you measure and see a problem.

编辑

我意识到我并没有真正回答这个问题……我认为简短的回答是不,它不会泄漏". (从某种特殊意义上来说,所有无限" IEnumerables(具有缓存的后备存储)都泄漏"(取决于定义泄漏"的方式),请参见

I realize I didn't really answer the question... I think the short answer is "no, it does not leak". (There is a special sense in which all 'infinite' IEnumerables (with a cached backing store) 'leak' (depending on how you define 'leak'), see

避免堆栈溢出(使用F#无限序列序列)

关于IEnumerable(也称为"seq")与LazyList的有趣讨论,以及消费者如何能够急切地使用LazyList来忘记"旧结果以防止某种泄漏".)

for an interesting discussion of IEnumerable (aka 'seq') versus LazyList and how the consumer can eagerly consume LazyLists to 'forget' old results to prevent a certain kind of 'leak'.)

这篇关于递归序列会泄漏内存吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆