A API de criação de perfil de rastreamento de objeto
Coleta de lixo recupera a memória ocupada por objetos inativos e pode compactar o espaço livre. Como resultado, os objetos vivos são movidos dentro da pilha. Este tópico explica como afeta o movimento do objeto ObjectID valores e como esses valores são controlados pela API de criação de perfil durante a compactação e sem compactação lixo coleção.
Movimento do objeto
Quando objetos são movidos, ObjectID valores que foram atribuídos por alterar notificações anterior. O estado interno do próprio objeto não altera, exceto para as suas referências a outros objetos. Somente o local do objeto na memória (e, portanto, sua ObjectID) as alterações. O ICorProfilerCallback::MovedReferences notificação permite que um gerador de perfil atualizar suas tabelas internas que rastreiam informações por ObjectID. O MovedReferences nome do método é um pouco enganador, porque ele é emitido, mesmo para os objetos que não foram movidos.
O número de objetos na heap pode numerar milhares ou milhões. Seria inviável para controlar o movimento de um número grande de objetos, fornecendo um antes e depois de ID para cada objeto. Portanto, o coletor de lixo tende a mover contíguos objetos vivos em blocos, de modo que elas fiquem contíguas em seus novos locais na heap. O MovedReferences relatórios de notificação do antes e depois ObjectIDs desses blocos contíguos de objetos.
Suponha que uma existente ObjectID valor (oldObjectID) encontra-se no intervalo a seguir:
oldObjectIDRangeStart[i] <= oldObjectID < oldObjectIDRangeStart[i] + cObjectIDRangeLength[i]
Nesse caso, o offset do início do intervalo para o início do objeto é o seguinte:
oldObjectID - oldObjectRangeStart[i]
Para qualquer valor de i que está no seguinte intervalo:
0 <= i < cMovedObjectIDRanges
Você pode calcular a nova ObjectID da seguinte maneira:
newObjectID = newObjectIDRangeStart[i] + (oldObjectID – oldObjectIDRangeStart[i])
Esses retornos de chamada são feitos enquanto o common language runtime (CLR) está suspenso. Portanto, nenhum dos valores ObjectID pode ser alterado até o tempo de execução será retomada e outra coleta de lixo ocorre.
A ilustração a seguir mostra os 10 objetos antes da coleta de lixo. Seus endereços de início (equivalente a ObjectIDs) são 08, 09, 10, 12, 13, 15, 16, 17, 18 e 19. Os objetos com ObjectIDs 09, 13 e 19 estão mortos, e seu espaço será recuperado durante a coleta de lixo.
Movimento do objeto durante a coleta de lixo
A parte inferior da ilustração mostra os objetos após a coleta de lixo. O espaço foi ocupado por objetos inativos tem foram recuperado para armazenar objetos vivos. Os objetos ao vivo na heap foram movidos para os novos locais que são mostrados. Como resultado, suas ObjectIDs irá alterar. A seguinte tabela mostra a ObjectIDs antes e após a coleta de lixo.
Object |
[] de oldObjectIDRangeStart |
[] de newObjectIDRangeStart |
---|---|---|
0 |
08 |
07 |
1 |
09 |
|
2 |
10 |
08 |
3 |
12 |
10 |
4 |
13 |
|
5 |
15 |
11 |
6 |
16 |
12 |
7 |
17 |
13 |
8 |
18 |
14 |
9 |
19 |
A tabela a seguir compacta informações especificando as posições e tamanhos de blocos contíguos de partida. Esta tabela mostra exatamente como o MovedReferences método relata informações.
Blocos |
[] de oldObjectIDRangeStart |
[] de newObjectIDRangeStart |
[] de cObjectIDRangeLength |
---|---|---|---|
0 |
08 |
07 |
1 |
1 |
10 |
08 |
2 |
2 |
15 |
11 |
4 |
Detectando todos os objetos excluídos
O MovedReferences método relata todos os objetos que sobrevivem a uma coleta de lixo compactando, independentemente de eles movidos. Qualquer objeto que não são relatado por MovedReferences não sobreviver. No entanto, nem todas as coletas de lixo estiver compactando. No.NET Framework versões 1.0 e 1.1, o criador de perfil não pôde detectar objetos que sobreviveram a uma coleta de lixo não compactação (uma coleta de lixo na qual não há objetos movidos em todos os). A.NET Framework versão 2.0 fornece melhor suporte para esse cenário através dos seguintes métodos novos:
O profiler pode chamar o ICorProfilerInfo2::GetGenerationBounds método para obter os limites de coleta de lixo em segmentos de pilha. O rangeLength campo resultante COR_PRF_GC_GENERATION_RANGE estrutura pode ser usada para determinar a extensão dos objetos ao vivo em uma geração compactada.
O ICorProfilerCallback2::GarbageCollectionStarted retorno de chamada que indica quais gerações estão sendo coletadas, a coleta de lixo atual. Todos os objetos que estão em uma geração que não está sendo coletada sobreviverão a coleta de lixo.
O ICorProfilerCallback2::SurvivingReferences retorno de chamada que indica quais objetos sobreviveram a uma coleta de lixo não compactar.
Observe que uma coleta de lixo único pode ser a compactação para uma geração e compactação em não para geração de outra. Ou seja, qualquer dada geração receberá um SurvivingReferences ou MovedReferences retornos de chamada para uma coleta de lixo determinado, mas não ambos.
Comentários
Após uma coleta de lixo, um aplicativo é interrompido até que o runtime tenha terminado de passar informações sobre a pilha para o criador de perfil de código. Você pode usar o ICorProfilerInfo::GetClassFromObject método para obter o ClassID da classe de. do objeto Você pode usar o ICorProfilerInfo::GetClassIDInfo ou ICorProfilerInfo2::GetClassIDInfo2 método para obter informações sobre a classe de metadados.
No.NET Framework versões 1.0 e 1.1, quando uma operação de coleta de lixo completa, todos os objetos sobreviventes é esperado para ser uma referência de raiz, para ter um pai que é uma referência de raiz ou existir em uma geração que não foi coletada. Às vezes, é possível ter objetos que não pertencem a qualquer uma dessas categorias. Esses objetos são alocados tanto internamente pelo tempo de execução ou são referências fracas para representantes. No.NET Framework 1.0 e 1.1, a API de criação de perfil não permitem ao usuário identificar esses objetos.
No.NET Framework versão 2.0, três métodos foram adicionados para ajudar o profiler para esclarecer exatamente quais gerações são coletadas e quando e para identificar quais objetos estão raízes. Esses métodos ajudam o profiler determinar por que os objetos permanecem após uma coleção:
O ICorProfilerCallback2::RootReferences2 método permite que o profiler identificar objetos que são mantidos por meio de alças especiais. A geração circunda informações fornecidas pelo ICorProfilerInfo2::GetGenerationBounds método combinado com as informações coletadas geração fornecidas pelo ICorProfilerCallback2::GarbageCollectionStarted método habilitar o profiler identificar objetos que existem em gerações que não foram coletadas.
Referência
Método de ICorProfilerCallback::MovedReferences
Método de ICorProfilerCallback2::SurvivingReferences
Método de ICorProfilerInfo2::GetGenerationBounds