株式会社空想科学テクノロジー

メモリの効率性

どこまでランタイムに任せるかを 5 段階から選べます。

効率性か高速性か

効率全て有効で動きます。回収、コンパクション、止まる時間の上限。これが既定の姿です。言語が保証するのは、この姿です。
速度要らない段階を、外せます。外した分だけ速く動きます。外すのはプログラマーの選択で、言語が保証する範囲外です。外した姿での動きは、プログラマーの責任になります。

効率性を下げるのは、速くするための調整です。 言語の側は、全て有効な姿だけを保証します。 そのため、5 通りの保証を引き受けることにはなりません。

5 段階の効率性

下から順に、1 つずつ足していきます。上の段階は、下の段階を全部含みます。

足すもの何が変わるか
0何も足しません手で確保し、手で返します。いまの C++ と同じです。
1参照カウントと、即時の解放スマートポインタに相当します。参照が無くなった瞬間に返します。
2循環参照の回収互いに参照し合ったものも返します。
3コンパクション空いた隙間を詰めます。ここで Java や C# と並びます。
4止まる時間を、プログラマーが決める1 周期(= ゲームなら 1 フレーム)の持ち時間の内側に収めます。これが既定の姿です。

3 で Java や C# と並び、4 が、それらに無いものです。4 は速さの段ではなく、止まり方の選択です。3 に下げても速くはならず、上限の無いコンパクションになります。

※ 2 と 3 の間に、境が 1 つあります。コンパクションではオブジェクトが動きますので、参照の仕組みが変わります。そのため、同じビルドの中で、1・2 と、3 以上を混ぜることはできません(= 0 は任せない側で、どの段階とも同居できます)。部品(= クラスの単位)ごとに段階を選べますが、ビルド全体でどちら側かを先に決め、その側の中で部品ごとに選びます。
※ メモリをどう確保するか(= 起動時に最大値を一括で確保し、足りなくなった時に伸ばすか止まるかを選ぶ)は、段階ではなく設定です。どの段階でも選べます。足りなくなったときの振る舞いは、YamatoMM の 取り扱い方法 に書きました。

何を外すと、何が変わるか

参照ごとに有効3 の参照の仕組み。外せば、そのまま速くなります。ビルド全体で 1・2 の側を選んだときです。
代入ごとに有効1 の参照カウントの増減。1 以上では外せません。
周期ごとに有効3 のコンパクション。ただし、外すと速くなるとは限りません。隙間が埋まらないまま残り、一緒に使うオブジェクトが離れて置かれるので、キャッシュに当たりにくくなります。長く動かすと、外した方が遅くなることがあります。

どの段階が何をしているかを知れば、速さは見積もれます。 そのため、段階ごとの数は出していません。

他の言語との違いは、「選べる」ではなく「選び直せる」ことです

コンパイラが証明できないことを人が保証する方法は、多くの言語にあります。 Rust の unsafe、C# の unsafe、Swift の UnsafePointer、Go の unsafe。 ただし、どれも「保証があるか、無いか」の 2 値です。Rust の unsafe の中でも借用や境界の検査は効きますが、許された操作(= 生ポインタの参照外しなど 5 つ)について、言語が保証するものはありません。

効率性は 5 段階です。下げても、何が残るかが判ります。 2 まで下げても「循環参照は回収する」という振る舞いは残り、3 と 4(= コンパクションと、止まる時間の上限)が外れます。

足すものRust(= 言語と標準ライブラリ)にあるか
0何も足しませんありますBox(= 所有者が 1 人の確保)です。生の確保と解放は unsafe の中です。
1参照カウントと、即時の解放ありますRcDrop です。
2循環参照の回収ありませんRc の循環参照は漏れますので、Weak を手で書きます。
3コンパクションありません回収の仕組みそのものがありません。
4止まる時間を、プログラマーが決めるありません回収で止まりませんので、概念が要りません。

目的も違います。 unsafe は、コンパイラが証明できないことを、人が保証するための方法です。 *C++ の各段階は、速くするための方法です。 unsafe が速さのために使われること(= 境界の検査を外すなど)もありますが、それは本来の目的ではなく、使い方です。

通常は、言語を選んだ時点で、メモリの管理の仕方も決まります。 Java や C# を選べば回収の仕組みを使い続け、Rust を選べば所有権の検査を受け続けます。 変えるには、別の言語で書き直すしかありません。 *C++ は、同じソースのまま、ビルドの仕方を変えます。 メモリの管理の仕方は、言語を選ぶときではなく、ビルドするときに決めます。

※ 速さは、お使いになる環境によって変わります。