- Jangan Takut Reaper
- Life in the Fast Lane
- Go Your Own Way. .
- Go Your Own Way. .
Dalam seri pertama tentang GC, saya memperkenalkan pengumpul sampah D dan fitur bahasa yang menggunakannya. Dua poin utama yang saya coba sampaikan:
GC hanya berjalan saat Anda meminta alokasi memori . Berlawanan dengan kesalahpahaman populer, bahasa D GC tidak bisa hanya menghentikan dan menjeda klon Minecraft Anda di tengah-tengah loop permainan. Ini hanya berjalan ketika Anda meminta memori melaluinya dan hanya jika diperlukan.
Strategi alokasi memori gaya C dan C ++ sederhana dapat mengurangi beban pada GC . Jangan mengalokasikan memori di dalam loop - sebagai gantinya, pra-alokasikan sumber daya sebanyak mungkin atau gunakan tumpukan. Minimalkan jumlah total alokasi memori melalui GC. Strategi ini berhasil karena # 1. Pengembang dapat menentukan kapan harus menjalankan pengumpulan sampah dengan cerdas menggunakan alokasi tumpukan yang dikelola GC.
Strategi dari poin # 2 baik untuk kode yang ditulis sendiri oleh programmer, tetapi mereka tidak terlalu membantu dalam hal perpustakaan pihak ketiga. Dalam kasus ini, menggunakan mekanisme bahasa D dan runtime-nya, Anda dapat memastikan bahwa tidak ada alokasi memori yang terjadi pada titik-titik kritis dalam kode. Ada juga opsi baris perintah untuk membantu memastikan GC tidak menghalangi Anda.
Mari kita bayangkan bahwa Anda sedang menulis program D dan karena satu dan lain hal memutuskan untuk menghapus seluruh pengumpulan sampah. Anda memiliki dua solusi yang jelas.
Pil untuk keserakahan
Solusi pertama adalah menelepon GC.disable
ketika program dimulai. Mengalokasikan memori melalui GC masih akan berfungsi, tetapi pengumpulan sampah akan berhenti. Semua pengumpulan sampah, termasuk apa yang mungkin terjadi pada utas lainnya.
void main() {
import core.memory;
import std.stdio;
GC.disable;
writeln("Goodbye, GC!");
}
Keluaran:
Goodbye, 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
. , , .
Dalam artikel mendatang, kita akan melihat bagaimana mengalokasikan memori tanpa menggunakan GC, dan menggunakannya secara paralel dengan memori dari GC, daripada mengganti @nogc
fitur bahasa yang tidak tersedia dalam kode, dan banyak lagi.
Terima kasih kepada Vladimir Panteleev, Guillaume Piolat dan Steven Schveighoffer atas umpan balik mereka yang berharga pada draft artikel ini.