From: SASADA Koichi Date: 2013-08-19T17:56:39+09:00 Subject: [ruby-dev:47640] Re: [ruby-trunk - Bug #8711] 最近NoMemoryErrorが多い (2013/08/19 15:42), KOSAKI Motohiro wrote: >> > 考えられる解決策: >> > - TestFiber#test_many_fibers を削除 >> > - TestFiber#test_many_fibers を別プロセスで実行 >> > - TestFiber#test_many_fibers 後にちゃんと物理メモリを解放するように頑張る > システム全体で制限がかかっているので別プロセスで実行は本質的では > ないように思います。 > ちゃんと開放するようにテスト(と、GC)を変えて、そもそもシステムの > メモリが小さすぎるときはテストをスキップするようにしないと、 > 不思議な箇所でエラーを吐くと思います。 プロセスが肥大化し、元に戻らないのが原因のようなので、とりあえず応急処置 にはなるかと。 で、fork() が失敗する条件は、一度に mmap できないような連続したメモリ領 域がある場合なのですが、何かと調べたり考えたりしたところ、(まだ確証はな いのですが)VM のスタックであることに思い至りました。 現状、VM stack は Fiber 生成時、および Fiber 解放時に割り当て、解放を ALLOC_N()、つまり malloc() 経由で行っています。これにはいくつか問題があ ります。 (1) Fiber の初回起動前、および Fiber の終了後には VM stack は不要 (2) malloc で割り当てているため、free しても OS に返すかどうかは不明 (1) は、単純に改良をすればいいだけです。ただし、変更はちょっと面倒そうです。 (2) は、例えば mmap にすれば解決しますが、システムコールのオーバヘッドを どう考えるか、ということになるかと思います。理想的には、Fiber が burst 的に発生する、という前提では、初期値は小さく、オーバーフローしそうになっ たら増やしていくような感じにしたいと思って居ます(これはスレッドも同 じ)。が、これは凄く面倒な話。 とりあえず、当該テストで GC.start をする、という腰砕けな対応になっています。 -- // SASADA Koichi at atdot dot net