(To.Double() || !To.double()) { return “That’s the question”; }

Aconteceu hoje de um cliente me questionar sobre a existência de um eventual overhead gerado por boxing e unboxing de variáveis do tipo Double (big D) contra a utilização de double (small d). Após explicar a ele que isto não existe pois ambas as variáveis são armazenadas no stack, notei que havia ficado aquela pitada de desconfiança e, para fechar o assunto de forma adequada, preparei um pequeno exemplo, segue:

public static double Testa_d()
{
double a = double.MinValue;
double b = (double)a + 3000.0;
return b + 1.0;
}
public static Double Testa_D()
{
Double a = Double.MinValue;
Double b = (Double)a + 3000.0;
return b + 1.0;
}
public static double Testa_dDMix()
{
double a = Double.MinValue;
Double b = (double)a + 3000.0;
return b + 1.0;
}

Neste código temos três métodos onde, em dois deles (Testa_d e Testa_D) trabalhamos com uma declaração unica dos tipos das variáveis a e b. Já no método Testa_dDMix, trabalhamos de forma “mista”.

Finalizando, para poder provar minha declaração recorri a um simples recurso prático:  ildasm.

Uma vez de posse do código IL gerado pelo compilador, foi só abrir e mostrar que todos os três métodos geraram uma representação idêntica e, não possuem qualquer instrução de boxing e/ou unboxing. Segue:

{
  // Code size       35 (0x23)
  .maxstack  2
  .locals init ([0] float64 a,
           [1] float64 b)
  IL_0000:  ldc.r8     -1.7976931348623157e+308
  IL_0009:  stloc.0
  IL_000a:  ldloc.0
  IL_000b:  conv.r8
  IL_000c:  ldc.r8     3000.
  IL_0015:  add
  IL_0016:  stloc.1
  IL_0017:  ldloc.1
  IL_0018:  ldc.r8     1.
  IL_0021:  add
  IL_0022:  ret
}

Note que ambas as variáveis são declaradas exatamente da mesma forma (linhas 4 e 5) e, apenas para sair um pouco do feijão com arroz e a título de curiosidade, note que na linha 9 existe uma chamada para conv.r8.

Em poucas palavras, isto ocorre pois no código C# nós escrevemos este fragmento utilizando conversão explicita e, mesmo sendo uma conversão para o mesmo tipo (o que em outro momento seria um óbvio erro de programação), o compilador parece não se importar em colocar esta diretiva extra. Pessoalmente tenho um apresso muito grande para com o compilador .Net, acho ele realmente phoda, mas neste caso ele meio que faz gordisse… Se alguém tiver uma boa explicação ou motivo que justifique esta diretiva neste caso, ficarei feliz em receber um feedback.

Abraço e até a próxima!

Update: Algumas pessoas me responderam falando pra tentar usar o sufixo D no valor da variável, porém, isto não muda em nada quanto a adição ou não da diretiva conv.r8 ao código.

Update 1 / Complemento: Uma referência legal pra quem quer saber um pouco mais sobre boxing e unboxing: IL 101–Parte 9 (Boxing e Unboxing)

2 comentários

  1. Felipe, fiquei em dúvida se realmente não existe um overhead, principalmente por essa diretiva extra. Digo isso porque esse overhead existe em Java(sem querer comparar os compiladores). Vou sugerir um teste: crie um laço que itere por milhões de vezes e, a cada passo, faça uma chamada a esses métodos com e sem unboxing que você já criou. Contabilize o tempo para as duas alternativas. Ai sim pode-se afirmar se há ou não alguma influência do unboxing no tempo de execução.

    Curtir

    • Esta diretiva em si pode até gerar algum overhead (na verdade, eu acredito que até deve existir mas só será perceptível quando você está trabalhando com uma necessidade de performance a nivel de ciclo de processador)… a questão toda gira em torno do uso ou não de boxing e unboxing, o que definitivamente não acontece neste caso
      Abraço!

      Curtir

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: