F# Seq.iter两种用途的性能差异很大

F# Seq.iter两种用途的性能差异很大,f#,iteration,seq,F#,Iteration,Seq,以下是说明我的问题的MWE: let f (n : int) : unit = {1 .. n} |> Seq.iter (fun s -> // Do something memory intensive, without retaining anything () ) () // First call f 100 // Second call {1 .. 10} |> Seq.iter (fun s

以下是说明我的问题的MWE:

let f (n : int) : unit =
    {1 .. n}
    |> Seq.iter (fun s ->
        // Do something memory intensive, without retaining anything
        ()
        )
    ()

// First call
f 100

// Second call
{1 .. 10}
|> Seq.iter (fun s -> f 10)
尽管两个调用的最终结果相同,但第一个调用的性能要比第二个调用差得多。第一次调用中的内存使用率高达95%,系统的速度减慢到爬行状态。第二个的内存使用率从未超过50%


有人能解释一下为什么,以及我应该如何预见到这一点吗?提前感谢您的帮助。

这是.Net JIT—代码第一次在解释器下运行。随后运行,代码被编译为机器代码,速度更快。因此,对于.Net性能基准测试,您总是在计时之前运行代码一次。尽管我像以前一样编写了MWE,但实际代码没有一种类型的调用紧跟着另一种类型的调用。我编译了这个项目,并不止一次地运行了每种类型的调用。每一次,第一种类型的调用的内存消耗都急剧上升。我认为问题在于,在第一种类型中,CLR在
f
中完成所有迭代之前不会尝试释放内存。在第二次调用中,每次调用
f
后,可能会从外部序列中释放内存。这有点违反直觉,因为我希望系统会发现
f
没有保留任何内容,从而在必要时释放内存。您能提供一个可复制的示例吗?在s=100或s=10的迭代中,您分配了多少内存?系统中有多少可用内存?如果系统在s=100左右耗尽内存,那么这种行为是正常的。我在iter上通过将一个大文件读入内存来测试你的代码。在这两种情况下,它似乎都很好。两种情况下生成的IL似乎也相同。