Os compiladores do .NET Framework implementam uma série de otimizações que são executadas no momento da compilação.
Isso corre para que o programador possa ter mais “clareza” ao ler um fonte e não perder performance durante a execução do mesmo.
Vamos abordar algumas destas otimizações que sendo de nosso conhecimento pode oferecer uma nova abordagem a problemas antigos e facilitar nosso dia a dia como programadores.
Para motivos didáticos os códigos compilados em C# serão obtidos dos códigos fontes em C# e os códigos compilados em VB.Net serão obtidos dos códigos fontes em VB.Net, desta forma poderemos observar se existem diferencias de otimizações entre os compiladores C#.Net e VB.Net
Constantes
Se algo é uma constante, então, ele “é o que é” e “será sempre o que é”, imutável em sua própria natureza e preso a sua própria e única existência.
Neste espírito o compilador troca todas as chamadas a uma constante pelo próprio valor da constante, evitando assim chamadas desnecessárias a posições de memória que poderiam (caso não acontece-se a troca) existir com o valor.
Fonte Original em C#
const string csvSeparator = ";"; const string endOfLineSeparator = "\n"; string nome = "Guilherme Bacellar Moralez"; int idade = 25; string sexo = "Masculino"; string dadoEmCSV = nome + csvSeparator + idade.ToString() + csvSeparator + sexo + endOfLineSeparator;
Fonte Original em VB.Net
Sub Main()
Const csvSeparator As String = ";"
Const endOfLineSeparator As String = vbCrLf
Dim nome As String = "Guilherme Bacellar Moralez"
Dim idade As Integer = 25
Dim sexo As String = "Masculino"
Dim dadoEmCSV As String = nome + csvSeparator + idade.ToString() + csvSeparator + sexo + endOfLineSeparator
End Sub
Resultado Compilado em C#
private static void Main(string[] args)
{
string nome = "Guilherme Bacellar Moralez";
int idade = 0x19;
string sexo = "Masculino";
string dadoEmCSV = nome + ";" + idade.ToString() + ";" + sexo + "\n";
}
Resultado Compilado em VB.Net
Public Shared Sub Main()
Dim nome As String = "Guilherme Bacellar Moralez"
Dim idade As Integer = &H19
Dim sexo As String = "Masculino"
Dim dadoEmCSV As String = String.Concat(New String() {nome, ";", idade.ToString, ";", sexo, ChrW(13) & ChrW(10)})
End Sub
Podemos observar que as variáveis que originalmente eram consideras constantes foram eliminadas do código fonte resultante e suas referências foram trocadas pelos próprios valores atribuídos originalmente às constantes.
Remoção de Itens não Usados
Para falar deste item, deixe-me introduzir uma pergunta: Você manteria o seu lixo em casa?
Acredito veementemente que a resposta um sonoro NÃO!!!!!!!
Bom, nem os compiladores do .NET (Atenção!!!!!, estamos falando neste artigo dos compiladores de C# e VB.NET) fazem isso.
Dentro do ciclo de processamento existe a capacidade de remover variáveis e blocos de código que nunca serão utilizados no programa, então, nada mais natural do que remover estes blocos.
Vamos pegar o exemplo acima e fazer uma leve mudança no código.
Fonte Original em C#
private static void Main(string[] args)
{
const string csvSeparator = ";";
const string endOfLineSeparator = "\n";
string nome = "Guilherme Bacellar Moralez";
int idade = 25;
string sexo = "Masculino";
string dadoEmCSV = nome + csvSeparator + idade.ToString() + csvSeparator + sexo;
if (dadoEmCSV.Equals("Guilherme Bacellar Moralez;25;Masculino"))
{
return;
}
dadoEmCSV += endOfLineSeparator;
}
Fonte Original em VB.Net
Sub Main()
Const csvSeparator As String = ";"
Const endOfLineSeparator As String = vbCrLf
Dim nome As String = "Guilherme Bacellar Moralez"
Dim idade As Integer = 25
Dim sexo As String = "Masculino"
Dim dadoEmCSV As String = nome + csvSeparator + idade.ToString() + csvSeparator + sexo
If (dadoEmCSV.Equals("Guilherme Bacellar Moralez;25;Masculino")) Then
Exit Sub
End If
dadoEmCSV = dadoEmCSV + endOfLineSeparator
End Sub
Resultado Compilado em C#
private static void Main(string[] args)
{
string nome = "Guilherme Bacellar Moralez";
int idade = 0x19;
string sexo = "Masculino";
string dadoEmCSV = nome + ";" + idade.ToString() + ";" + sexo;
if (!dadoEmCSV.Equals("Guilherme Bacellar Moralez;25;Masculino"))
{
dadoEmCSV = dadoEmCSV + "\n";
}
}
Resultado Compilado em VB.Net
Public Shared Sub Main()
Dim nome As String = "Guilherme Bacellar Moralez"
Dim idade As Integer = &H19
Dim sexo As String = "Masculino"
Dim dadoEmCSV As String = String.Concat(New String() {nome, ";", idade.ToString, ";", sexo})
If Not dadoEmCSV.Equals("Guilherme Bacellar Moralez;25;Masculino") Then
dadoEmCSV = (dadoEmCSV & ChrW(13) & ChrW(10))
End If
End Sub
Uma vez detectado que, existe uma linha de código que nunca será utilizada no código fonte, o compilador remove esta linha do Build final. De quebra, foi removida a linha que declarava a constante “endOfLineSeparator”, afinal, o único ponto em que ela seria utilizada nunca será chamado pelo código fonte.
Otimizações Aritméticas
1 + 1 = 2
2 + 2 = 4
((1 + 2) * 3) * (99 / (3 * 4)) = 74,25
Um computador é (no fundo) uma máquina de calcular extremamente sofisticada, então, o que ele sabe fazer de melhor é realizar operações matemáticas.
Da mesma forma os compiladores conseguem realizar otimizações de formulas e cálculos de nosso código para evitar que sejam executadas operações de forma desnecessária.
Fonte Original em C#
private static void Main(string[] args)
{
int idadeInicial = 25;
double modificadorIPrevidencia = 0.69 + 1;
double modificadorIIPrevidencia = 9.9999 - 0.001 ;
double modificadorIIIPrevidencia = modificadorIPrevidencia*modificadorIIPrevidencia;
double valorCotaPrevidencia = 0.2236977;
double totalValorInvestido = 1000000;
double totalCotas;
totalCotas = (totalValorInvestido/valorCotaPrevidencia) * ((modificadorIIPrevidencia / (modificadorIPrevidencia / idadeInicial))) * modificadorIIIPrevidencia;
}
Fonte Original em VB.Net
Sub Main()
Dim idadeInicial As Integer = 25
Dim modificadorIPrevidencia As Double = 0.69 + 1
Dim modificadorIIPrevidencia As Double = 9.9999 - 0.001
Dim modificadorIIIPrevidencia As Double = modificadorIPrevidencia * modificadorIIPrevidencia
Dim valorCotaPrevidencia As Double = 0.2236977
Dim totalValorInvestido As Double = 1000000
Dim totalCotas As Double
totalCotas = (totalValorInvestido / valorCotaPrevidencia) * ((modificadorIIPrevidencia / (modificadorIPrevidencia / idadeInicial))) * modificadorIIIPrevidencia
End Sub
Resultado Compilado em C#
private static void Main(string[] args)
{
int idadeInicial = 0x19;
double modificadorIPrevidencia = 1.69;
double modificadorIIPrevidencia = 9.9989;
double modificadorIIIPrevidencia = modificadorIPrevidencia * modificadorIIPrevidencia;
double valorCotaPrevidencia = 0.2236977;
double totalValorInvestido = 1000000.0;
double totalCotas = ((totalValorInvestido / valorCotaPrevidencia) * (modificadorIIPrevidencia / (modificadorIPrevidencia / ((double)idadeInicial)))) * modificadorIIIPrevidencia;
}
Resultado Compilado em VB.Net
Public Shared Sub Main()
Dim idadeInicial As Integer = &H19
Dim modificadorIPrevidencia As Double = 1.69
Dim modificadorIIPrevidencia As Double = 9.9989
Dim modificadorIIIPrevidencia As Double = (modificadorIPrevidencia * modificadorIIPrevidencia)
Dim valorCotaPrevidencia As Double = 0.2236977
Dim totalValorInvestido As Double = 1000000
Dim totalCotas As Double = (((totalValorInvestido / valorCotaPrevidencia) * (modificadorIIPrevidencia / (modificadorIPrevidencia / CDbl(idadeInicial)))) * modificadorIIIPrevidencia)
End Sub
Observemos que ocorreram algumas otimizações:
Otimizações de Declaração de Variáveis
Código fonte mais “legível” não significa necessariamente código fonte mais lento.
Em diversas ocasiões trabalhei com equipes que me diziam que declarar uma variável e depois atribuir o valor a ela (em linhas diferentes) era mais lento do que declarar a variável e atribuir o valor no momento da declaração.
Nada melhor do que decompilar para aprender, então…
Fonte Original em C#
private static void Main(string[] args)
{
// Declara as Constantes
const string csvSeparator = ";";
const string endOfLineSeparator = "\n";
// Declara as Variáveis
string nome;
int idade;
string sexo;
string dadoEmCSV = "";
string dadoLoop;
// Preenche as Variáveis
sexo = "Masculino";
nome = "Guilherme Bacellar Moralez";
idade = 25;
for (int i = 0; i <= idade; i++)
{
dadoLoop = nome;
dadoLoop += csvSeparator;
dadoLoop += idade.ToString();
dadoLoop += csvSeparator;
dadoLoop += sexo;
dadoLoop += endOfLineSeparator;
dadoEmCSV += dadoLoop;
}
}
Fonte Original em VB.Net
Sub Main()
' Declara as Constantes
Const csvSeparator As String = ";"
Const endOfLineSeparator As String = "\n"
' Declara as Variáveis
Dim nome As String
Dim idade As Integer
Dim sexo As String
Dim dadoEmCSV As String = ""
Dim dadoLoop As String
' Preenche as Variáveis
sexo = "Masculino"
nome = "Guilherme Bacellar Moralez"
idade = 25
For i As Integer = 0 To idade
dadoLoop = nome
dadoLoop += csvSeparator
dadoLoop += idade.ToString()
dadoLoop += csvSeparator
dadoLoop += sexo
dadoLoop += endOfLineSeparator
dadoEmCSV += dadoLoop
Next
End Sub
Resultado Compilado em C#
private static void Main(string[] args)
{
string dadoEmCSV = "";
string sexo = "Masculino";
string nome = "Guilherme Bacellar Moralez";
int idade = 0x19;
for (int i = 0; i <= idade; i++)
{
string dadoLoop = nome;
dadoLoop = ((dadoLoop + ";") + idade.ToString() + ";") + sexo + "\n";
dadoEmCSV = dadoEmCSV + dadoLoop;
}
}
Resultado Compilado em VB.Net
Public Shared Sub Main()
Dim dadoEmCSV As String = ""
Dim sexo As String = "Masculino"
Dim nome As String = "Guilherme Bacellar Moralez"
Dim idade As Integer = &H19
Dim VB$t_i4$L0 As Integer = idade
Dim i As Integer = 0
Do While (i <= VB$t_i4$L0)
Dim dadoLoop As String = nome
dadoLoop = (((dadoLoop & ";") & idade.ToString & ";") & sexo & "\n")
dadoEmCSV = (dadoEmCSV & dadoLoop)
i += 1
Loop
End Sub
Vamos observar atentamente as mudanças realizadas
Conclusões
A que conclusões podemos chegar:
Bom, eu cheguei a 2 delas:
Posts Relacionados:



January 22nd, 2009 at 5:10 AM
[...] ao ler um fonte e não perder performance durante a execução … fique por dentro clique aqui. Fonte: [...]