Jump to content


Photo

Vb.net - Otimização E Performance


  • Faça o login para participar
1 reply to this topic

#1 MACUL

MACUL

    Doutor

  • Usuários
  • 770 posts
  • Sexo:Masculino
  • Localidade:SP

Posted 06/10/2006, 09:34

VB.NET - Otimização e Performance

Veremos nessa matéria, dicas e regras para melhorarmos a performance de nossas aplicações usando Visual Basic .NET.

Quantas vezes nós já ouvimos falar que a linguagem X é mais rápida que a linguagem Y? Ou que a linguagem W é mais segura que a linguagem Z? Isso gera algumas discursões que nunca tem fim. Mas no fundo, o que acontece na maioria das vezes é que os programadores se esquecem que o quanto uma linguagem é segura ou performática depende quase sempre da forma como ela é usada e para que fim ela é usada.

Para não causar polêmica, vou comparar duas linguagens da Microsoft, o VB6 e VB.NET. Quando o VB.NET chegou ao mercado, em 2001, vi muitos desenvolvedores dizendo que o VB6 era muito mais rápido do que o VB.NET, e cansei de responder perguntas em fóruns de discursão onde o cidadão até dava exemplo disso. Bem, na grande maioria das vezes eles estavam errados, o problema é que não dominavam a nova linguagem, menos ainda o ambiente de desenvolvimento, portanto o que faziam era simplesmente a conversão de VB6 -> VB.NET. E isso está bem longe de ser a melhor forma de se comparar performance. Quando refiz muito destes códigos, tchan, tchan, tchan, milagre! O código em VB.NET foi mais rápido. Por que?

Veremos isso nas próximas linhas. Procure ter em mente a dobradinha: Performance X Segurança. Onde a segurança é o foco, a performance sai prejudicada e vice versa, embora ambas tenham sempre que andar juntas. Ache o meio termo.

Como esse assunto é muito amplo, vou dividi-lo em partes:

- Tipos de Dados
- Declarações
- Operações
- Procedimentos
- Outras Otimizações

Tipos de Dados
O tipo de dado que você escolhe para suas variáveis, propriedades, argumentos de procedimentos, variáveis de retorno, enfim, tudo isso afeta em muito a performance de sua aplicação.

Value Type x Reference Type

Tipos Value Type armazenam seus valores no seu próprio espaço de memória e são alocados na memória chamada Stack. Já os Reference Type guardam no seu espaço de memória apenas um ponteiro para o local onde o dado está armazenado, e que ficam em um espaço de memória chamado Heap.

O gerenciamento da Heap é bem mais caro que o do Stack, devido à alocação de memória, acesso ao dado via referência, GC (Garbage Collection), etc. Isso significa que a escolha por um tipo Value Type na maioria das vezes é a melhor escolha. Contudo, os Value Types tem uma desvantagem: Ocupam mais espaço na memória. No final, a melhor opção é: Caso você não necessite da flexibilidade dos Reference Type, use os objeto do tipo Value type.

Para saber mais:

http://msdn.microsof...rfvbspec6_1.asp

http://msdn.microsof...rfvbspec6_2.asp

Early e Late Binding e o tipo Object

Uma variável declarada como Object pode apontar (lembre-se do tipo Reference Type) para qualquer tipo de objeto. Essa flexibilidade tem um custo muito grande devido ao fato de esse tipo de variável ser sempre Late Bound. Quando o seu código acessa membros dessa variável, o CLR é obrigado a realizar checagem de tipo e procurar esse membro dentro do objeto em tempo de execução.

Os objetos declarados como Early Bound tem uma performance significantemente superior aos Late bound. O seu código se torna mais legível e o número de erros em tempo de execução cai significativamente.

Portanto, evite o uso de variáveis do tipo Object quando não for estritamente necessário.

Para saber mais:

http://msdn.microsof...LateBinding.asp

Tamanho dos tipos de dados

O tipo de dado mais eficiente é aquele que é usa o tamanho de dado nativo da plataforma. Ou seja, na plataforma de 32 bits o tipo de dados com 32 bits será o mais rápido. No .NET o tipo de dado que possui esse tamanho é o tipo Integer ou Int32. O próximo mais performático é o Long, e em seguida vem o Short e Byte. Pode não parecer, mas embora o tipo Integer seja maior do que o Short e o Byte, mesmo assim ele é mais rápido. Caso você queira usar o Short ou Byte e obter uma performance parecida com o do tipo Integer, desabilite a checagem de Overflow. É uma prática que eu desaconselho, principalmente por que hoje em dia memória já não é um grande problema.

Caso você precise valores fracionários, a melhor escolha é o tipo Double, já que os processadores de ponto flutuante realizam suas operações em precisão dupla. Depois vem o tipo Single e Decimal.

Box e Unboxing

Boxing é um processamento extra que o CLR faz quando você trata um Value Type como um Reference Type. Isso é necessário quando, por exemplo: Você declara um tipo Integer e atribui a ele um tipo de variável Object ou passa-o para uma procedure que receba um Object como argumento. Neste caso, o CLR precisa converter a variável para o tipo Object.

Se você subseqüentemente atribuir uma variável que sofreu boxing para uma variável Value Type, o CLR irá reverter isso. Esse processo chama-se Unboxing.

Boxing e Unboxing, geram uma degradação de performance muito grande. Portanto se sua aplicação faz constantes operações como essa, prefira declarar o objeto inicialmente como Reference Type. Outra forma de evitar isso é definir a diretiva Option Strict On.

Arrays

Quanto menor a dimensão do array melhor a performance, então procure calcular bem o quanto você terá que usar, para não alocar espaço desnecessariamente.

Jagged Arrays ( Array de Array ) são bem mais eficientes do que o array multidimensional, ou seja, A(6)(6) é mais eficiente do que A(6,6). Isto é devido ao fato de os Jagged Arrays sofrerem uma otimização para um array de uma dimenção. Só para constar, ele é aproximadamente 30% mais eficiente.

ArrayList

Essa classe é ideal para utilizar quando o array é dinâmico, ou seja, sobre muita alteração na sua dimensão. Usar ArrayList é muito mais performático do que usar o ReDim. A desvantagem do ArrayList é que os seus membros são do tipo Object, logo, Late Bound. Mas a vantagem sobre o uso do ReDim é tão grande que compensa essa desvantagem.

Nessa primeira parte, vimos como o uso do tipo de dado correto pode tornar seu código mais eficiente. Na próxima parte iremos ver mais dicas sobre operações, procedimentos e outras otimizações. Até breve.

Leonardo Bruno Lima
lblima_net@hotmail.com
Microsoft MVP (Most Valuable Professional)
Trabalha com desenvolvimento de aplicações .NET desde 2001. Ministra cursos sobre a plataforma .NET, é consultor de tecnologia e desenvolvedor de sistemas na RR Consultoria e Sistemas (Fortaleza - CE).
Atualmente está dedicado ao desenvolvimento de um sistema ERP utilizando a plataforma .NET



VB.NET - Otimização e Performance - Parte II

Vimos na primeira parte dessa matéria como o uso do tipo de dado correto pode tornar o seu código mais eficiente. Veremos agora mais algumas dicas.

Declarações
Vimos na matéria anterior que usar Early Binding é mais performático do que usar Late binding. Mas mesmo quando usamos Early Binding, devemos ter certeza de declarar o objeto do tipo mais específico possível. Vejamos um exemplo:

Hierarquia da classe Label:

System.Object
System.MarshalByRefObject
System.ComponentModel.Component
System.Windows.Forms.Control
System.Windows.Forms.Label

Hierarquia da classe Button:

System.Object
System.MarshalByRefObject
System.ComponentModel.Component
System.Windows.Forms.Control
System.Windows.Forms.ButtonBase
Syste m.Windows.Forms.Button

Se desejarmos criar um objeto que possa referenciar tanto um Button quanto um Label, devemos declará-lo como Control, que é a classe mais próxima de ambos. O que ocorre, é que muitas vezes quando nos deparamos com essa situação, declaramos o objeto como Object, e isso é um erro muito comum.

Propriedades, Variáveis e Constantes

Desconsiderando o conceito de encapsulamento e focando em performance, podemos dizer que é melhor utilizar variáveis ao invés de propriedades. Variáveis fazem acesso simplesmente ao local da memória onde está o dado, enquanto propriedades exigem chamadas extras dos métodos Get e Set, o que gera um processamento adicional.

Cuidado também com variáveis declaradas com "WithEvents", pois o compilador implementa-as como propriedades.

Já as constantes são bem superiores às variáveis, pois seus valores são compilados dentro do código e não exigem pesquisa nem acesso à memória, exceto as constantes do tipo Date ou Decimal.

Options Settings

Usar Option Explicit On, força você declarar todas as variáveis, o que torna o seu código mais legível e menos sujeito a erros. Procure usar sempre essa opção ativa. Procure também usar declaração de variável usando "As", caso contrário ela será do tipo Object, o que já vimos não ser um tipo ótimo.

Option Strict On desabilita as conversões implícitas e obriga todas as variáveis serem declaradas utilizando "As". Dessa forma, o Late binding é desabilitado, a não ser que você declare explicitamente o objeto como Object.

Option Compare binary define que as strings serão comparadas e ordenadas com base na sua representação binária. Isso aumenta a performance.

Acesso a disco

Temos básicamente 3 (três) maneiras de acessar arquivos com o Visual Basic .NET:

• Usando as funções de compatibilidade do VB: OpenFile, WriteLine, etc

• Usando o FSO (FileSystemObject)

• Usando as classes do Namespace System.IO


As duas primeiras opções existem por questões de compatibilidade entre as versões anteriores do VB (FSO para scripts). Mas na verdade elas são implementadas em Wrapper Objects que encapsulam o acesso às classes do Namespace System.IO, sendo assim, nem precisa dizer que acessar utilizando diretamente as classes do System.IO é bem mais eficiente.

Início da página
Operações
Algumas coisas são óbvias, mas às vezes não seguimos. Por exemplo, se vamos fazer operações entre variáveis onde não importa a parte decimal ou fracionária, não faz sentido declarar a variável como um tipo diferente de Integer ou Long. Da mesma forma se na operação entre os inteiros não lhe importa o resto, use o operador "\" ao invés de "/", isso é mais ou menos 10 vezes mais rápido.

Concatenções

Sempre que você for concatenar Strings, use o operador "&" e evite o uso do operador "+". O segundo, realiza checagem de tipo em tempo de execução, o que obviamente causa uma perda de performance.

Caso a quantidade de strings que serão concatenadas seja muito grande, use a classe StringBuilder, e você verá a visível diferença de velocidade. Exemplo:

Dim s As String
Dim sb As New StringBuilder

For i As Integer = 0 To 100000
sb.Append(i.ToString & " ")
Next

For i As Integer = 0 To 100000
S &= i.ToString & " "
Next

Execute os dois loops. Não vale babar ao notar a diferença de velocidade.

Strings Functions

É muito comum a conversão e/ou formatação de strings em nossos programas. No VB temos a função Format, que formata a string de acordo com a formatação passada como parâmetro. Mas quando trabalhamos com .NET, essa função (Que ainda existe por questões de compatibilidade) realiza muitas verificações, conversões e outros processamentos incluindo formatação de acordo com a cultura corrente, e isso é claro torna o código menos eficiente. Prefira usar o método "ToString". Ele é muito mais rápido do que a função Format em relação à formatação e muito mais eficiente do que o método CStr, por exemplo, em relação a conversão.

Em relação aos métodos Asc e Chr, ambos trabalham com caracteres single-byte e double-byte, e o valor de retorno depende do Code page da Thread atual. Já os métodos AscW e ChrW trabalham exclusivamente com caractere Unicode, e são independentes da cultura e do Code page da Thread atual, sendo assim mais eficientes. Só como observação, o tipo String no .NET é representado como uma seqüência de caracteres Unicode.

Testes Booleanos

Não existe diferença de performance entre fazer um teste de uma variável booleana usando o sinal de igual "=" ou simplesmente usando a própria variável sozinha.

Exemplo:

Dim Flag as Boolean
If Flag = True ...

É igual a:

Dim Flag as Boolean
If Flag ...

Mas a segunda forma é mais compacta e consequentemente torna o seu código menor, claro que isso é um detalhe, mas eu achei interessante mostrar.

Curto circuito

Sempre que possível use os operadores AndAlso e OrElse. Eles evitam avaliações desnecessárias, tipo:

Dim A1, A2, A3, ... as Boolean
A1 = True
A2 = False
A3 = True
...

If A1 AndAlso A2 AndAlso A3 … then ...

No caso acima, ao verificar que A2 é falso, não faz sentido continuar a avaliar as outras variáveis, no caso a A3, pois sempre o resultado será Falso.

Início da página
Procedimentos
Tamanho do procedimento

Todos os procedimentos ( functions e Subs ) estão sujeitos ao JIT (Just-in-Time) compilation, ou seja, ele não é compilado até a primeira vez que ele é acessado. O JIT tenta realizar algumas otimizações enquanto compila o procedimento, como geração de código inline no caso de procedimentos pequenos. Se o procedimento for grande, ele não gozará dessa otimização. O ideal é que ele tenha menos que 1000 linhas de código.

Chamadas e Retorno

Nas versões anteriores do VB, o local onde a chamada de um método era feita, fazia diferença na performance da aplicação, ou seja, se uma função chamasse outra no mesmo módulo, era mais rápido do que chamar uma função em outro módulo. No VB.NET, isso não faz diferença.

Use "Return" sempre que precisar retornar algo a partir da função, pois o compilador irá otimizar o código de forma melhor do que se você usar Exit Function, Exit Sub, "NomeFunção = ValorRetorno", etc.

Argumentos

Quando você passa um argumento para um método usando ByRef, o VB.NET copiará apenas o ponteiro para o local onde a variável está armazenada na memória. Tanto faz se o tipo passado é Reference Type ou Value Type. Já se passar usando ByVal (Default no VB.NET), o conteúdo da variável será copiado. No caso de Reference Types, como o seu conteúdo é apenas um ponteiro, não irá fazer diferença.

Em relação à performance de ambos, na maioria dos casos não há diferença significante entre as duas formas, especialmente entre os Reference Types.

Obs.: Caso o argumento seja um objeto muito grande, usar ByVal gerará um Overhead devido a cópia do objeto. Nesse caso, prefira usar ByRef.

Chamadas entre processos

Evite chamadas entre processos, chamadas remotas e chamadas entre Application Domains, devido ao overhead gerado pelo uso de marshaling.

Quando você realmente precisar fazer isso, procure usar poucas chamadas "Chunky" (que realiza muitas operações de uma só vez) no lugar de muitas chamadas "Chatty" (que faz poucas operações em uma chamada)

Tipos Blittable

São tipos que possuem a mesma representação tanto na memória gerenciada (runtime .NET) ou não gerenciada. E por isso podem ser copiados através de chamadas entre códigos gerenciados e não gerenciados sem a necessidade de conversão. Os tipos Blittable são:

• System.Byte

• System.SByte

• System.Int16

• System.UInt16

• System.Int32

• System.UInt32

• System.Int64

• System.IntPtr

• System.UIntPtr


Nessa segunda parte, vimos algumas dicas sobre declarações, operações e procedimentos. Na terceira e última parte, veremos algumas dicas sobre o uso do ambiente de desenvolvimento e outras otimizações. Até breve.

Leonardo Bruno Lima
lblima_net@hotmail.com
Microsoft MVP (Most Valuable Professional)
Trabalha com desenvolvimento de aplicações .NET desde 2001. Ministra cursos sobre a plataforma .NET, é consultor de tecnologia e desenvolvedor de sistemas na RR Consultoria e Sistemas (Fortaleza - CE).
Atualmente está dedicado ao desenvolvimento de um sistema ERP utilizando a plataforma .NET


http://www.microsoft...erformance.mspx
http://www.microsoft...rformance2.mspx

VB.NET - Otimização e Performance - Parte III

Nesta última parte veremos outras dicas importantes e alguns recursos do Visual Studio .NET que facilitam a nossa vida e aumentam a produtividade.

Compilação e Precompilação
Todo código fonte é compilado para Microsoft Intermediate Language (MSIL). O MSIL reside em arquivos .exe e .dll, que serão lidos pelo compilador JIT (Just-in-Time), que faz parte do CLR (Common Language Runtime). Normalmente o compilador JIT, compila cada procedimento para código nativo na primeira vez que o procedimento é chamado.

Bem, isso na maioria dos casos é muito útil, mas não em todos. Digamos que sua aplicação faça muitas chamadas a procedimentos na inicialização, e essas chamadas demandem algum tempo de processamento. Esse é um típico caso onde a Pré-compilação pode ser uma boa alternativa.

Você pode compilar partes de sua aplicação utilizando a ferramenta "ngen.exe". O Ngen, não invoca o JIT, ao invés disso, ele faz a sua própria compilação, nesse caso, sem algumas otimizações que o JIT faz. Por isso tive o cuidado de dizer que: "...a Precompilação pode ser uma boa alternativa." O ideal é que ao faze-la, sejam feitos testes de performance para assegurar-se que o resultado é o esperado.

Para saber mais: http://msdn.microsof...atorngenexe.asp

Início da página
Debug e Release Builds
Podemos aumentar a performance compilando em modo Release ao invés do modo Debug. Isso faz com que o seu código IL seja menor e mais rápido devido a algumas otimizações que o compilador faz. Contudo, essas otimizações reordenam o código tornando a tarefa de debugar mais difícil. Traduzindo isso: Sempre que for distribuir uma versão do seu programa, compile em modo Release.

Início da página
Exceptions
Sem dúvida a forma de tratar as exceções no VB.NET é bem mais robusta que nas versões anteriores. Mas elas tem um custo caro para a performance de sua aplicação, mas não é por isso que você vai deixar de usar os blocos Try ... Catch, esse custo é cobrado apenas quando a exceção é disparada. Portanto, não dispare exceções gratuitamente ou para controlar o fluxo do programa.

Eu sei que muita gente faz isso, por isso veja esse exemplo e tire suas próprias conclusões:

Chame essa rotina no evento clique de um botão.

Me.Cursor = Cursors.WaitCursor
For i As Integer = 0 To 10000
Try
Throw New ApplicationException("Minha exceção")
Catch ex As Exception
Debug.WriteLine(Ex.Message)
End Try
Next
Me.Cursor = Cursors.Default

Agora execute o código abaixo e veja a diferença.

Me.Cursor = Cursors.WaitCursor
For i As Integer = 0 To 10000
Try
Debug.WriteLine("Minha exceção")
Catch ex As Exception

End Try
Next
Me.Cursor = Cursors.Default

Início da página
Preenchimento de controles
Todo controle que você precisa preencher com grande quantidade de dados, sofrerá com o "Repaint", ou seja, poderá tremer (o conhecido flicker) enquanto o mesmo é preenchido. Em alguns controles temos meios de evitar isso como nos controles: ComboBox, DataGridColumnStyle, ListBox, ListView e TreeView. Para esses controles, sempre que você for adicionar novos itens, utilize antes de iniciar a inclusão, o método BeginUpdate e ao finalizar o método EndUpdate. Com esses métodos, obtemos também uma melhor performance no preenchimento dos controles. Podemos também utilizar sempre que o objeto disponibilizar o método AddRange, que é mais rápido do que a inclusão individual de itens. Veja na prática a diferença de performance:

Execute esse código:

Me.Cursor = Cursors.WaitCursor
For i As Integer = 0 To 10000
Me.ListBox1.Items.Add("Item " & i.ToString)
Next
Me.Cursor = Cursors.Default

E agora execute chamando os métodos descritos acima:

Me.Cursor = Cursors.WaitCursor
Me.ListBox1.BeginUpdate()
For i As Integer = 0 To 10000
Me.ListBox1.Items.Add("Item " & i.ToString)
Next
Me.ListBox1.EndUpdate()
Me.Cursor = Cursors.Default

Para finalizar, vejamos algumas dicas rápidas sobre produtividade no Visual Studio .NET:

As animações das janelas por default vem habilitadas, para desabilitar as animações do ambiente de desenvolvimento vá ao menu Tools -> Options, e na pasta Environment escolha a opção General. Então, desmarque a opção: "Animate Environment Tools".

Dynamic Help, muito útil, mas é um trabalho a mais para processador e memória. Matenha-o fechado, a menos que o custo de mante-lo aberto seja compensador para você, o que na maioria dos casos não é. É melhor utilizar a janela Index do que o dynamic Help.

Clipboard ring, use quando estiver editando o código, ele fica disponível na Toolbox quando visualizamos o código da classe. Com ele você pode utilizar o recurso copy paste. Ele é muito útil quando temos que atualizar várias partes do código com textos que estejam na memória.

Configuration Manager, utilize para definir que projetos de sua solução irão ser compilados. Muitas vezes temos uma solução com vários projetos, e quando estamos trabalhando em apenas um ou dois, às vezes não faz sentido compilar tudo, então basta ir ao menu Build -> Configuration Manager e marcar apenas os projetos que você deseja compilar. Pode parecer besteira, mas quantas vezes por dia não precisamos rodar a aplicação para testes?

Na Start Page, podemos configurar o nosso profile. Para tornar o carregamento do Visual Studio mais rápido, vá em My Profile e em "At Startup" selecione a opção: Show Empty Environment.

Nessa última parte, vimos algumas considerações finais sobre o tema performance. Tive a preocupação de manter um nível técnico intermediário nessas matérias, com o objetivo de fazer despertar nos programadores que estão iniciando no mundo .NET a importância desse tema e introduzir alguns conceitos que devem estar presentes no nosso dia a dia. Até a próxima e aguardo sugestões.

Leonardo Bruno Lima
lblima_net@hotmail.com
Microsoft MVP (Most Valuable Professional)
Trabalha com desenvolvimento de aplicações .NET desde 2001. Ministra cursos sobre a plataforma .NET, é consultor de tecnologia e desenvolvedor de sistemas na RR Consultoria e Sistemas (Fortaleza - CE).
Atualmente está dedicado ao desenvolvimento de um sistema ERP utilizando a plataforma .NET

http://www.microsoft...rformance3.mspx
*************** M ** A ** C ** U ** L ***************

*************************************************

#2 Miguceamma

Miguceamma

    MiguPenjisse

  • Usuários
  • 13201 posts

Posted 22/11/2017, 11:21

Amoxicillin Reactions To Alcohol levitra canada price Priligy Durchfall Propecia How To Apply Cialis 20 Mg Preiswert




1 user(s) are reading this topic

0 membro(s), 1 visitante(s) e 0 membros anônimo(s)

IPB Skin By Virteq