为什么在F#中使用Seq.take抛出System.OutOfMemoryException

时间:2013-08-20 12:18:45

标签: memory-management f# sequence

我有一个代码:

seq {for i in [1 .. 100000000] -> i} |> Seq.take 100000;;
Real: 00:00:00.000, CPU: 00:00:00.000, GC gen0: 0, gen1: 0, gen2: 0
val it : seq<int> =
  Error: Exception of type 'System.OutOfMemoryException' was thrown.

此代码导致内存不足。为什么?为什么在计算时间后(操作完成后)会抛出异常? AFAIK,个别序列元素仅在需要时计算?

2 个答案:

答案 0 :(得分:8)

seq {for i in [1 .. 100000000] -> i} |> Seq.take 100000

从列表[1 .. 100000000]创建一个将根据您的要求生成项目的序列。这要求列表在内存中。该列表对于32位内存来说太大了,因此OutOfMemoryException。你应该试试

seq {for i in 1 .. 100000000 -> i} |> Seq.take 100000

答案 1 :(得分:6)

除了揭示核心问题的原因之外,可能有必要解决问题的第二部分,即为什么在操作完成后抛出异常。

为了理解这一点,这将有助于考虑

let mySeq = seq {for i in [1 .. 100000000] -> i} |> Seq.take 100000;;

不会出现任何例外情况,而看似无害

seq {for i in [1 .. 100000000] -> i};;

之后会出现与原版相同的异常,尽管我们似乎无论如何都不会尝试实现序列。

没错,我们没有,但是 FSI确实,试图打印出几个第一序列成员的值,比如下面的一个较小的列表:

 seq {for i in [1 .. 100] -> i};;
 val it : seq<int> = seq [1; 2; 3; 4; ...]

启动原始庞大列表的内存实例化。

相关问题