- Não tema o ceifador
- Vida na pista rápida
- Go Your Own Way. .
- Go Your Own Way. .
Na primeira de uma série no GC, apresentei o coletor de lixo D e os recursos de idioma que o utilizam. Dois pontos-chave que tentei transmitir:
O GC é executado somente quando você solicita uma alocação de memória . Ao contrário do equívoco popular, o GC da linguagem D não pode simplesmente pausar e pausar seu clone do Minecraft no meio de um ciclo de jogo. Só é executado quando você solicita memória através dele e somente quando necessário.
Estratégias simples de alocação de memória no estilo C e C ++ podem reduzir a carga no GC . Não aloque memória dentro de loops - em vez disso, pré-aloque o máximo de recursos possível ou use a pilha. Minimize o número total de alocações de memória através do GC. Essas estratégias funcionam por causa do nº 1. O desenvolvedor pode determinar quando executar a coleta de lixo usando inteligentemente a alocação de heap gerenciada por GC.
As estratégias do ponto 2 são adequadas para o código que o programador escreve, mas não são particularmente úteis quando se trata de bibliotecas de terceiros. Nesses casos, usando os mecanismos da linguagem D e seu tempo de execução, você pode garantir que nenhuma alocação de memória ocorra em pontos críticos do código. Também existem opções de linha de comando para ajudar a garantir que o GC não atrapalhe.
Vamos imaginar que você esteja escrevendo um programa em D e, por um motivo ou outro, resolva eliminar completamente a coleta de lixo. Você tem duas soluções óbvias.
Comprimido para ganância
A primeira solução é ligar GC.disable
quando o programa for iniciado. A alocação de memória via GC ainda funcionará, mas a coleta de lixo será interrompida. Toda a coleta de lixo, incluindo o que pode ter acontecido em outros threads.
void main() {
import core.memory;
import std.stdio;
GC.disable;
writeln("Goodbye, GC!");
}
Resultado:
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
. , , .
Em artigos futuros, veremos como alocar memória sem recorrer ao GC e usá-lo em paralelo com a memória do GC, do que substituir os @nogc
recursos de idioma que não estão disponíveis no código e muito mais.
Agradecemos a Vladimir Panteleev, Guillaume Piolat e Steven Schveighoffer por seus valiosos comentários sobre o rascunho deste artigo.