Pergunta

Eu li recentemente uma discussão sobre se gerenciado idiomas são mais lentas (ou mais rápido) do que as línguas nativas (especificamente C # vs C ++). Uma pessoa que contribuiu para a discussão disse que os compiladores JIT de idiomas gerenciados seria capaz de fazer otimizações sobre as referências que simplesmente não é possível em idiomas que usam ponteiros.

O que eu gostaria de saber é que tipo de otimizações que são possíveis em referências e não em ponteiros?

Note que a discussão era sobre a velocidade de execução, não uso de memória.

Foi útil?

Solução

Há alguns benefícios de compilação JIT mencionado na Wikipedia:

código JIT geralmente oferece um desempenho muito melhor do que os intérpretes. Além disso, ele pode em alguns ou muitos casos, oferecem melhor desempenho do que a compilação estática, como muitas otimizações só são viáveis ??em tempo de execução:

  1. A compilação pode ser otimizado para a CPU alvo eo modelo de sistema operacional em que o aplicativo é executado. Por exemplo JIT pode escolher instruções SSE2 CPU quando detecta que a CPU suporta-los. Com um compilador estático deve escrever duas versões do código, possivelmente usando linha de montagem.
  2. O sistema é capaz de coletar estatísticas sobre como o programa está realmente em execução no ambiente que se encontra, e pode reorganizar e recompilação para um melhor desempenho. No entanto, alguns compiladores estáticos também pode ter informações de perfil como entrada.
  3. O sistema pode fazer otimizações de código globais (por exemplo inlining de funções da biblioteca) sem perder as vantagens de ligação dinâmica e sem as despesas gerais inerentes ao compiladores estáticos e linkers. Especificamente, ao fazer substituições em linha globais, um compilador estático deve inserir verificações de tempo de execução e garantir que uma chamada virtual poderia ocorrer se a classe real do objeto substitui o método inline.
  4. Embora isso é possível com linguagens de lixo coletado estaticamente compiladas, um sistema de bytecode pode memorizar mais facilmente reorganizar para uma melhor utilização do cache.

Eu não consigo pensar em algo relacionado diretamente ao uso de referências em vez de ponteiros.

Outras dicas

Em C ++, há duas vantagens de referências relacionadas com aspectos de otimização:

  1. Uma referência é constante (refere-se à mesma variável para toda a sua vida útil)

    Por isso, é mais fácil para o compilador para inferir quais os nomes se referem às mesmas variáveis ??subjacentes - criando assim oportunidades de otimização. Não há garantia de que o compilador vai fazer melhor com referências, mas talvez ...

  2. Uma referência é assumida para se referir a alguma coisa (não há nenhuma referência null)

    Uma referência que "refere-se a nada" (equivalente ao ponteiro nulo) pode ser criado, mas esta não é tão fácil como a criação de um ponteiro nulo. Devido a isso a verificação da referência para NULL podem ser omitidos.

No entanto, nenhuma dessas vantagens transitar directamente para idiomas gerenciados, então eu não vejo a relevância de que, no contexto do seu tópico de discussão.

Em linguagem geral, referências tornam possível para se referir ao mesmo objeto de diferentes lugares.

A 'ponteiro' é o nome de um mecanismo para implementar referências. C ++, Pascal, C ... tem ponteiros, C ++ oferece outro mecanismo (com um pouco de outros casos de uso) chamado de 'referência', mas essencialmente estas são todas as implementações do conceito geral de referência.

Portanto, não há razão pela qual as referências são, por definição, mais rápido / mais lento do que os ponteiros.

A verdadeira diferença está no uso de um JIT ou um 'up front' compilador clássico: o JIT pode dados levar em conta que não estão disponíveis para o up compilador frente. Não tem nada a ver com a implementação do conceito de 'referência'.

Outras respostas estão certas.

Gostaria apenas de acrescentar que qualquer otimização não fará a mínima diferença a menos que seja no código onde o contador de programa realmente gasta muito tempo, como nos laços apertados que não contêm chamadas de função (como cordas comparando).

Uma referência de objeto em um quadro gerenciado é muito diferente de uma referência aprovada em C ++. Para entender o que os torna especiais, imagine como o seguinte cenário seria tratado, no nível da máquina, sem referências de objeto coleta de lixo: Método "Foo" retorna uma string, que é armazenado em várias coleções e passou a diferentes partes do código. Uma vez que nada precisa a corda mais, deve ser possível recuperar toda a memória usada em armazená-lo, mas não está claro qual pedaço de código será o último a usar a string.

Em um sistema não-GC, cada coleção ou precisa ter a sua própria cópia do string, ou necessidades outra pessoa a algo espera que contém um ponteiro para um objeto compartilhado que contém os caracteres na cadeia. Nesta última situação, o objeto compartilhado precisa de alguma forma, saber quando o último ponteiro para ele é eliminado. Há uma variedade de maneiras isso pode ser tratado, mas um aspecto essencial comum de todos eles é que objetos compartilhados precisa ser notificado quando ponteiros para eles são copiados ou destruídos. Tal notificação requer trabalho.

Em um sistema de GC por outro lado, os programas são decorados com metadados para dizer que registros ou partes de um quadro de pilha será usado a qualquer momento para manter referências a objetos enraizadas. Quando um ciclo de coleta de lixo ocorre, o coletor de lixo terá que analisar esses dados, identificar e preservar todos os objetos vivos, e tudo bomba nuclear mais. Em todas as outras vezes, no entanto, o processador pode copiar, substituir, shuffle, ou destruir referências em qualquer padrão ou seqüência que gosta, sem ter de notificar qualquer dos objetos envolvidos. Observe que ao usar notificações ponteiro de uso em um sistema multi-processador, se diferentes segmentos podem copiar ou destruir referências para o mesmo objeto, código de sincronização será obrigado a fazer thread-safe a notificação necessária. Por outro lado, num sistema de GC, cada processador pode alterar as variáveis ??de referência a qualquer momento, sem ter de sincronizar a sua acção, com qualquer outro processador.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top