速い車線での生活



GCに関するシリーズの最初の記事では、Dガベージコレクターとそれを使用する言語機能を紹介しました。私が伝えようとした2つの重要なポイント:



  1. GCは、メモリ割り当てを要求したときにのみ実行されます一般的な誤解に反して、D言語のGCはMinecraftクローンをゲームループの途中で一時停止および一時停止することはできません。それがメモリを要求したときと、必要なときにだけ実行されます。



  2. 単純なCおよびC ++スタイルのメモリ割り当て戦略により、GCの負荷を軽減できます。ループ内にメモリを割り当てないでください。代わりに、できるだけ多くのリソースを事前に割り当てるか、スタックを使用してください。GCを介したメモリ割り当ての総数を最小限に抑えます。これらの戦略は#1のために機能します。開発者は、GC管理のヒープ割り当てをインテリジェントに使用して、ガベージコレクションをいつ実行するかを指示できます。





ポイント2のストラテジーは、プログラマーが自分で作成するコードには適していますが、サードパーティのライブラリに関しては特に役立ちません。このような場合、D言語とそのランタイムのメカニズムを使用して、コードの重要なポイントでメモリ割り当てが発生しないようにすることができます。GCが邪魔にならないようにするためのコマンドラインオプションもあります。



Dでプログラムを作成していて、何らかの理由でガベージコレクションを完全に排除することにしたとしましょう。あなたには2つの明白な解決策があります。



欲の丸薬



最初の解決策はGC.disable、プログラムの起動時に呼び出すことです。GCによるメモリの割り当ては引き続き機能しますが、ガベージコレクションは停止します。他のスレッドで発生した可能性があることを含む、すべてのガベージコレクション。



void main() {
    import core.memory;
    import std.stdio;
    GC.disable;
    writeln("Goodbye, GC!");
}


出力:



Goodbye, GC!


, , GC, , . , , , . , - . :



, , .

, . , - , . GC.enable GC.collect. , C C++.





, @nogc. main, .



@nogc
void main() { ... }


GC. @nogc, main, , . « ».



, GC.disable. .



@nogc
void main() {
    import std.stdio;
    writeln("GC be gone!");
}


:



Error: @nogc function 'D main' cannot call non-@nogc function 'std.stdio.writeln!string.writeln'
(: @nogc- 'D main'    -@nogc– 'std.stdio.writeln!string.writeln')


@nogc , . . @nogc, , , @nogc. , writeln .



:



@nogc 
void main() {
    auto ints = new int[](100);
}


:



Error: cannot use 'new' in @nogc function 'D main'
(:   'new'  @nogc- 'D main')


@nogc- , GC ( ). . , , GC . , , @nogc, .



, @nogc , . , , - ( ). — . :



throw new Exception("Blah");


- , new, @nogc- . , , , - , … , . D , , throw new Exception GC, .



, @nogc- . (. .)

@nogc main — , .



, : @nogc main GC . D . main, — . @nogc, , , GC @nogc-. , @nogc, main, , main , , GC.





. , D, GC . , GC — . , , D: GC . , , .



, , , GC. @nogc / API core.memory.GC . @nogc main, , GC. GC.disable . , GC.enable. , GC (, ), GC.collect.



, , , . API core.memory.GC GC . D.



( !) D --DRT-gcopt=profile:1, . GC, , .



: gcstat.d .



void main() {
    import std.stdio;
    int[] ints;
    foreach(i; 0 .. 20) {
        ints ~= i;
    }
    writeln(ints);
}


GC:



dmd gcstat.d
gcstat --DRT-gcopt=profile:1
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
        Number of collections:  1
        Total GC prep time:  0 milliseconds
        Total mark time:  0 milliseconds
        Total sweep time:  0 milliseconds
        Total page recovery time:  0 milliseconds
        Max Pause Time:  0 milliseconds
        Grand total GC time:  0 milliseconds
GC summary:    1 MB,    1 GC    0 ms, Pauses    0 ms <    0 ms


, , , . D GC , ( ) . , , D , GC - ( ).



DMD -vgc, GC — , , ~=.



: inner.d.



void printInts(int[] delegate() dg)
{
    import std.stdio;
    foreach(i; dg()) writeln(i);
} 

void main() {
    int[] ints;
    auto makeInts() {
        foreach(i; 0 .. 20) {
            ints ~= i;
        }
        return ints;
    }

    printInts(&makeInts);
}


makeInts — . , , / ( static, delegate function). .



-vgc:



dmd -vgc inner.d
inner.d(11): vgc: operator ~= may cause GC allocation
inner.d(7): vgc: using closure causes GC allocation

(inner.d(11): vgc:  ~=      GC)
(inner.d(7): vgc:        GC)


, , ints, ( — - delegate). ints makeInts . , - . printInts :



void printInts(scope int[] delegate() dg)


scope , . , dg . , . . , , .





, GC D , Java C#, . , D , Java, . , D. , Java, GC , .



, , , , . D № 2 , @nogc core.memory.GC , . , , , .



, D. , Phobos — D — @nogc. , , .



今後の記事では、GCに頼らずにメモリを割り当てる方法を検討し、GCからのメモリと並行して使用して、@nogcコードで利用できない言語機能などを置き換える方法を説明します。



この記事のドラフトに関する貴重なフィードバックを提供してくれたウラジミールパンテレエフ、ギヨームピオラット、スティーブンシュベイゴッファーに感謝します。




All Articles