Tempo de inicialização do aplicativo
A quantidade de tempo que é necessário para iniciar um aplicativo do WPF pode variar consideravelmente. Este tópico descreve diversas técnicas para reduzir o tempo de inicialização percebido e real de um aplicativo do WPF (Windows Presentation Foundation).
Noções básicas sobre a inicialização a frio e a inicialização a quente
A inicialização a frio ocorre quando o aplicativo é iniciado pela primeira vez após um reinício do sistema ou quando você inicia seu aplicativo, fecha-o e, em seguida, o inicia novamente após um longo período de tempo. Quando um aplicativo é iniciado, se as páginas necessárias (código, dados estáticos, Registro, etc) não estão presentes na lista de espera do Gerenciador de memória do Windows, ocorrem falhas de página. O acesso ao disco é necessário para colocar as páginas na memória.
A inicialização a quente ocorre quando a maioria das páginas dos componentes principais do CLR (Common Language Runtime) já está carregada na memória, o que economiza tempo valioso de acesso a disco. É por isso que um aplicativo gerenciado é iniciado mais rapidamente quando é executado pela segunda vez.
Implementar uma tela inicial
Em casos em que há um atraso significativo e inevitável entre o início de um aplicativo e a exibição da primeira interface do usuário, otimize o tempo de inicialização percebido através de uma tela inicial. Essa abordagem exibe uma imagem quase que imediatamente após o usuário iniciar o aplicativo. Quando o aplicativo estiver pronto para exibir sua primeira interface do usuário, a tela inicial desaparece. A partir do .NET Framework 3.5 SP1, você pode usar a SplashScreen classe para implementar uma tela inicial. Para obter mais informações, consulte Adicionar uma tela inicial a um aplicativo do WPF.
Você também pode implementar sua própria tela inicial, usando gráficos do Win32 nativos. Exiba sua implementação antes que o Run método seja chamado.
Analisar o código de inicialização
Determine o motivo de uma inicialização a frio lenta. A E/S do disco pode ser a responsável, mas nem sempre é o caso. Em geral, você deve minimizar o uso de recursos externos, como rede, serviços Web ou disco.
Antes de testar, verifique se não há outros aplicativos ou serviços em execução que usam código gerenciado ou código do WPF.
Inicie o aplicativo do WPF imediatamente após um reinício e determine quanto tempo ele demora para ser exibido. Se todas as inicializações subsequentes do seu aplicativo (inicialização a quente) forem muito mais rápidas, o problema de inicialização a frio será provavelmente causado pela E/S.
Se o problema de inicialização a frio do seu aplicativo não está relacionado à E/S, é provável que seu aplicativo realize algumas inicializações ou computações mais demoradas, aguarde algum evento ser concluído ou exija muita compilação JIT durante a inicialização. As seções a seguir descrevem algumas dessas situações com mais detalhes.
Otimizar o carregamento de módulo
Use ferramentas como o Explorador de Processos (Procexp.exe) e Tlist.exe para determinar quais módulos são carregados pelo seu aplicativo. O comando Tlist <pid>
mostra todos os módulos que são carregados por um processo.
Por exemplo, se você não estiver se conectando à Web e notar que a System.Web.dll é carregada, há um módulo em seu aplicativo que faz referência a esse assembly. Verifique se a referência é necessária.
Se seu aplicativo tem vários módulos, mescle-os em um único módulo. Essa abordagem requer menos sobrecarga de carregamento de assemblies do CLR. Menos assemblies também significam que o CLR mantém menos estado.
Adiar operações de inicialização
Considere a possibilidade de adiar o código de inicialização para depois que a janela do aplicativo principal for renderizada.
Lembre-se que a inicialização pode ser realizada dentro de um construtor de classe e, se o código de inicialização faz referência a outras classes, isso pode causar um efeito em cascata, em que vários construtores de classe são executados.
Evitar a configuração do aplicativo
Considere a possibilidade de evitar a configuração do aplicativo. Por exemplo, se um aplicativo tem requisitos de configuração simples e tem metas de tempo de inicialização estritas, as entradas de Registro ou um arquivo INI simples pode ser uma alternativa de inicialização mais rápida.
Utilizar o GAC
Se um assembly não estiver instalado no GAC (cache de assembly global), haverá atrasos causados pela verificação de hash de assemblies de nomes fortes e pela validação da imagem de Ngen, se uma imagem nativa desse assembly estiver disponível no computador. A verificação de nome forte é ignorada para todos os assemblies instalados no GAC. Para obter mais informações, consulte Gacutil.exe (ferramenta de cache de assembly global).
Usar Ngen.exe
Considere usar o gerador de imagem nativa (Ngen.exe) em seu aplicativo. O uso do Ngen.exe significa negociar o consumo de CPU por mais acesso ao disco, porque a imagem nativa gerada pelo Ngen.exe é, provavelmente, maior que a imagem MSIL.
Para melhorar o tempo de inicialização a quente, você deve usar sempre o Ngen.exe em seu aplicativo, porque isso evita o custo de CPU da compilação JIT do código do aplicativo.
Em alguns cenários de inicialização a frio, o uso do Ngen.exe também pode ser útil. Isso porque o compilador JIT (mscorjit.dll) não terá que ser carregado.
Ter módulos Ngen e JIT pode ter o efeito pior. Isso ocorre porque a mscorjit.dll deve ser carregada e quando o compilador JIT trabalha em seu código, muitas páginas nas imagens Ngen devem ser acessadas quando o compilador JIT lê os metadados dos assemblies.
Ngen e ClickOnce
A maneira como você planeja implantar seu aplicativo também pode fazer diferença no tempo de carregamento. A implantação do aplicativo ClickOnce não oferece suporte ao Ngen. Se você decidir usar o Ngen.exe para o seu aplicativo, terá que usar outro mecanismo de implantação, como o Windows Installer.
Para obter mais informações, consulte Ngen.exe (Gerador de Imagens Nativas).
Troca de base e colisões de endereço de DLL
Se você usar o Ngen.exe, lembre-se de que a troca de base poderá ocorrer quando as imagens nativas forem carregadas na memória. Se uma DLL não for carregada como seu endereço básico preferido, porque esse intervalo de endereços já está alocado, o carregador do Windows carregará a DLL em outro endereço, o que poderá ser uma operação demorada.
Você pode usar a ferramenta de despejo de endereço virtual (Vadump.exe) para verificar se há módulos nos quais todas as páginas são particulares. Se esse for o caso, o módulo poderá ter tido a base trocada para um endereço diferente. Portanto, suas páginas não podem ser compartilhadas.
Para obter mais informações sobre como definir o endereço básico, consulte Ngen.exe (Gerador de Imagens Nativas).
Otimizar Authenticode
A verificação de Authenticode aumenta o tempo de inicialização. Os assemblies assinados por Authenticode precisam ser verificados com a AC (autoridade de certificação). Essa verificação pode ser demorada, porque pode exigir a conexão com a rede várias vezes para baixar as listas atuais de revogação de certificados. Ela também verifica se há uma cadeia completa de certificados válidos no caminho para uma raiz confiável. Isso pode significar vários segundos de atraso enquanto o assembly está sendo carregado.
Considere a instalação do Certificado de Autoridade de Certificação no computador cliente ou evite o uso de Authenticode quando for possível. Se você sabe que seu aplicativo não precisa de prova do editor, não é necessário pagar pelo custo da verificação de assinatura.
A partir do .NET Framework 3.5, há uma opção de configuração que permite que a verificação do Authenticode seja ignorada. Para fazer isso, adicione a seguinte configuração no arquivo app.exe.config:
<configuration>
<runtime>
<generatePublisherEvidence enabled="false"/>
</runtime>
</configuration>
Para obter mais informações, consulte <o elemento generatePublisherEvidence>.
Comparar o desempenho no Windows Vista
O gerenciador de memória no Windows Vista tem uma tecnologia chamada SuperFetch. O SuperFetch analisa os padrões de uso de memória ao longo do tempo para determinar o conteúdo de memória ideal para um usuário específico. Ele funciona continuamente para manter esse conteúdo em todos os momentos.
Essa abordagem difere da técnica de pré-busca usada no Windows XP, que pré-carrega os dados na memória sem analisar padrões de uso. Ao longo do tempo, se o usuário usa o aplicativo do WPF com frequência no Windows Vista, o tempo de inicialização a frio do seu aplicativo pode melhorar.
Usar AppDomains com eficiência
Se possível, carregue os assemblies em uma área do código de domínio neutro para certificar-se de que a imagem nativa, se houver, é usada em todos os AppDomains criados no aplicativo.
Para um melhor desempenho, imponha uma comunicação eficiente entre domínios, reduzindo as chamadas entre domínios. Quando possível, use chamadas sem argumentos ou com argumentos de tipo primitivo.
Usar o atributo NeutralResourcesLanguage
Use o NeutralResourcesLanguageAttribute para especificar a cultura neutra para o ResourceManager. Essa abordagem evita pesquisas de assembly sem êxito.
Usar a classe BinaryFormatter para serialização
Se você precisar usar a serialização, use a BinaryFormatter classe em vez da XmlSerializer classe. A BinaryFormatter classe é implementada na BCL (Biblioteca de Classes Base) no assembly mscorlib.dll. O XmlSerializer é implementado no assembly System.Xml.dll, que pode ser uma DLL adicional a ser carregada.
Se você precisar usar a XmlSerializer classe, poderá obter um melhor desempenho se pré-gerar o assembly de serialização.
Configurar o ClickOnce para verificar se há atualizações após a inicialização
Se o aplicativo usar o ClickOnce, evite o acesso à rede na inicialização configurando o ClickOnce para verificar se há atualizações no site de implantação após a inicialização do aplicativo.
Se você usar o modelo XBAP (aplicativo de navegador XAML), lembre-se de que o ClickOnce verifica se há atualizações no site de implantação, mesmo que o XBAP já esteja no cache do ClickOnce. Para obter mais informações, consulte Segurança e implantação do ClickOnce.
Aviso
Os XBAPs exigem navegadores legados para operar, como o Internet Explorer e versões antigas do Firefox. Esses navegadores mais antigos geralmente não são compatíveis com Windows 10 e Windows 11. Os navegadores modernos não suportam mais a tecnologia necessária para aplicativos XBAP devido a riscos de segurança. Plug-ins que habilitam XBAPs não são mais suportados. Para obter mais informações, consulte Perguntas frequentes sobre aplicativos hospedados no navegador do WPF (XBAP).
Configurar o serviço PresentationFontCache para iniciar automaticamente
O primeiro aplicativo do WPF a ser executado após um reinício é o serviço PresentationFontCache. O serviço armazena em cache as fontes do sistema, melhora o acesso à fonte e melhora o desempenho geral. Há uma sobrecarga na inicialização do serviço e, em alguns ambientes controlados, considere a possibilidade de configurar o serviço para iniciar automaticamente quando o sistema for reiniciado.
Definir a vinculação de dados programaticamente
Em vez de usar XAML para definir a DataContext declarativamente para a janela principal, considere defini-la programaticamente no OnActivated método.
Confira também
.NET Desktop feedback