済むので、トータルの実行時間は短くなる、という話です。この辺の話題は、次の記事にまとまっています。導入した、と紹介しました。これによって、最大停止時間は(マーク+スイープの全部の処理)から(マーク+スイープの一部の処理)となりました。そもそもマークの時間が長いので、あまり問題は解決していませんでした。やると、以前と同様に全部のオブジェクトを対象とするため、停止時間の問題は厳然として存在します。GC)などのテクニックが知られています。アルゴリズムをご紹介します。進めていくための仕組みです。まとめてくれていました。IncrementalGC。ググれば色々出てきます。つのカテゴリに分けます。白:マークされていないオブジェクト灰:マークされており、これからこのオブジェクトから直接辿れるオブジェクトをマークしようとしているオブジェクト黒:マークされたオブジェクト、このオブジェクトから直接辿れるオブジェクトはすべてマーク済みである通常のマーク&スイープですと、白か黒しか無かったのですが、灰状態のオブジェクトが増えています。初期状態として、ルートオブジェクトを灰状態にしてマークスタックに積んでおきます。マークを複数のステップに分け、プログラムを実行しながらときどきマークのステップを実行し、処理を進めていきます。ステップは次のようになります。マークスタックから灰状態のオブジェクトを取り出し、黒状態にします。そのオブジェクトから直接辿れる白オブジェクトを灰状態にしてマークスタックに積みます。何回かこれを繰り返すとステップを終了します。これを進めていくと、段々白が灰、黒になっていくことがわかると思います。最終的に、マークスタックが空になると処理が終了します。生きているオブジェクトは黒、死んでいる(用済みとなった)オブジェクトは白となっているため、白を回収しておしまいです。灰状態のオブジェクトは残りません。ちなみに、細かいことを言うと、本当は最後にルートオブジェクトの再スキャンが必要になります。ルートオブジェクトが変化しているかもしれないからです。実行が進んで、黒状態のオブジェクトから白状態へのオブジェクトを参照してしまうような場合です。白、というときに起こります。このようなことが起こると、「黒状態のオブジェクトから直接辿れるオブジェクトはすべてマーク済みである」という前提が崩れてしまうので、問題です。マークされず白状態のままになり、間違えて回収されてしまうことになります。同様にライトバリアによってチェックします。灰状態に戻し、マークスタックに積みます。白から黒にマークされます。インクリメンタルにする方法は知られているので、興味がある人はググってみて下さい。GC(のマーク処理)にはライトバリアが必要であることがわかりました。「ライトバリアで保護されたオブジェクト」と「ライトバリアで保護されないオブジェクト」を適切に処理することで、とご紹介しました。ライトバリアが不完全なわけです。これは、ちゃんと動かせるでしょうか。ライトバリアがないと、どうまずいか考えてみます。マーク処理終了後に、「ライトバリアで保護されない黒状態のオブジェクト」から、「白状態のオブジェクト」への参照がある場合にまずいことがわかります。これをどうすれば良いか。これを対処するために、マーク終了時に「黒状態のライトバリアで保護されていないオブジェクト」全部を再スキャンすることでこの問題に対処します。再スキャン後、発見した「白状態のオブジェクト」を一気に(インクリメンタルではなく)マークしていきます。これによって、適切にマークを終了することができます。残っている「白状態のオブジェクト」の数に比例する時間になります。毎回マークされるため)、まぁ、いいかなー、と思っている次第です。凄くでかくなって停止時間が延びちゃいますが。「黒状態のライトバリアで保護されていないオブジェクト全部を再スキャン」と言ったのですが、これを行なうためには、何も考えないとすべてのオブジェクトをチェックして、「生きている」かつ「ライトバリアで保護されていない」ことをチェックしなければなりません。アプリでも数百万オブジェクト作るので、全部見て回ると凄い時間がかかります。管理するようにしました(それまではオブジェクトについているフラグでした)。論理積をチェックすることで、高速に走査することができます。実測してみると、そんなに時間がかかっていないことがわかります。おまけですが、これまで「ライトバリアで保護されていないオブジェクト」をオブジェクトについているフラグとして管理していた、と紹介していましたが、このフラグが無用になりました。数えられるカウンタを作り、オブジェクトの年齢を管理するようにしました。歳になると旧世代のオブジェクトとします。経験しないと旧世代のオブジェクトにならないことになります。回数を増やしてしまうことになるので、このようにしています。そのほか、いろんな処理の整理をしました。チューニング¶アルゴリズム自体は簡単だし、実装もすでに述べたところを注意すれば、ちゃんと動くものができるのですが、実はチューニングが難しいです。処理を同時に進めなければならないため、ある程度空き領域を用意しておかなければならないが、それはどれくらい用意しなければならないのか、といったパラメータを適切に検討する必要があるためです。プログラムが進めなくなってしまい、結局長時間の停止時間になってしまう可能性があります。短すぎると、アプリが十分に進めないまま、マークステップが始まってしまう、といった問題があります。コントロールするためのパラメータをユーザが指定できるようになっています。そのようにするべきか、それとも、もっと賢く、自動的に適切なパラメータを考えて用意するか、など、考えることが多いです。この辺の検討は十分じゃないので今後も進めていきたいです。用意することができました。本当の停止時間を知ることが出来ます。興味がある人は、これを使ったプロファイラを作って貰えるといいんじゃないかと思います。ついて、アルゴリズムとその実装を紹介しました。してリリースされる予定です。実は、まだチューニングが十分じゃ無いかもしれなくて、本当に停止時間が短くなっているかチェックがうまくいっていない状態です。リリースされる前でも試して貰えると助かります。LangLoading...。