大きなデータ(〜250 MB〜1 GB)で動作するアルゴリズムを実装しています。このために、ベンチマークを行うためのループが必要でした。しかし、このプロセスでは、F#がいくつかの厄介なことをしていることを知っています。あなたの一部が明確にできることを願っています。ここでF#コンパイラは死んだオブジェクトを生かしておく
は私のコードは、(問題の記述は以下である)である:ここでは
open System
for i = 1 to 10 do
Array2D.zeroCreate 10000 10000 |> ignore
printfn "%d" (GC.GetTotalMemory(true))
Array2D.zeroCreate 10000 10000 |> ignore
// should force a garbage collection, and GC.Collect() doesn't help either
printfn "%d" (GC.GetTotalMemory(true))
Array2D.zeroCreate 10000 10000 |> ignore
printfn "%d" (GC.GetTotalMemory(true))
Array2D.zeroCreate 10000 10000 |> ignore
printfn "%d" (GC.GetTotalMemory(true))
Array2D.zeroCreate 10000 10000 |> ignore
printfn "%d" (GC.GetTotalMemory(true))
Console.ReadLine() |> ignore
出力は以下のようになります:ループF#で、だから、
54000
54000
54000
54000
54000
54000
54000
54000
54000
54000
400000000
800000000
1200000000
Out of memory exception
結果を破棄しますが、とき私はループの中にいません。F#は "死んだデータ"への参照を保持します(私はILを見てきましたが、明らかにクラスのプログラムはこのデータのフィールドを取得します)。どうして?それを修正できますか?
このコードは、Visual Studioおよびリリースモード以外で実行されます。
+1ありがとう、面白い:)最初の解決策は動作しますが、無視して無視するとここでは役立ちません。私はまだそれが何をするのかを調べることにはまだ興味があります。 –
興味深い...最適化を有効にするために '-O'オプションで試してみました。 –
奇妙な。私がVisual Studioの外でそれを実行したときも、ここでもうまくいきました。しかし、今度はループがメモリ不足例外を発生させましたが、最初に "non-loop"バージョンを実行した場合のみ:/私はローカルスコープに固執するでしょう。 –