Haskell での遅延評価がスペース リークにつながる場合があることを何度も読みました。スペース リークを引き起こす可能性があるのは、どのようなコードですか? それらを検出する方法は?また、それらを回避するためにプログラマー側でどのような予防策を講じることができますか?
2 に答える
おそらく多くの回答が得られるでしょう。これは、「現実世界」のアプリケーションを実行しようとしたときに遭遇したものです。マルチスレッドといくつかの MVar を使用してデータをやり取りしていました (MVar はロックされた共有メモリのようなものです)。私の典型的なパターンは次のとおりです。
a <- takeMVar mvar
putMVar mvar (a + 1)
そして、ときどき、適切な状況が発生したときに、次のようなことを行いました。
a <- takeMVar mvar
when (a > 10) ....
問題は、mvar の内容が基本的に (0 + 1 + 1 + 1 + ....) であったことです...これは 100k のような数値では非常に集中的でした... このタイプの問題は私のコードにかなり蔓延していました。残念ながら、マルチスレッド アプリケーションでは、このような問題に陥りやすいです。
検出...私がしたことは、メモリ消費に関するデータを生成するモードでhaskellを開始し、さまざまなスレッドを開始および停止し、メモリフットプリントが安定しているかどうかを確認することでした...
大規模なデータ構造に対して再帰を実行しているときに、この問題に遭遇しました。蓄積されたサンクが多すぎると、スペース リークが発生します。
Haskell では、スペース リークが発生する可能性を常に意識する必要があります。反復が存在しないため、基本的に再帰関数はスペース リークを生成する可能性があります。
この問題を回避するには、再帰関数をメモ化するか、末尾再帰的に書き直します。