Tempo de inicialização do aplicativo
A quantidade de tempo necessária para iniciar um aplicativo WPF pode variar muito. Este tópico descreve várias técnicas para reduzir o tempo de inicialização percebido e real para um aplicativo Windows Presentation Foundation (WPF).
Entendendo a inicialização a frio e a inicialização quente
A inicialização a frio ocorre quando o aplicativo é iniciado pela primeira vez após uma reinicialização do sistema, ou quando você inicia o aplicativo, feche-o e inicie-o 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 estiverem presentes na lista de espera do gerenciador de memória do Windows, ocorrerão falhas de página. O acesso ao disco é necessário para trazer as páginas para a memória.
A inicialização quente ocorre quando a maioria das páginas dos principais componentes CLR (Common Language Runtime) já estão carregadas na memória, o que economiza tempo dispendioso de acesso ao disco. É por isso que um aplicativo gerenciado é iniciado mais rápido quando é executado pela segunda vez.
Implementar uma tela inicial
Nos casos em que há um atraso significativo e inevitável entre iniciar um aplicativo e exibir a primeira interface do usuário, otimize o tempo de inicialização percebido usando uma tela inicial . Essa abordagem exibe uma imagem quase imediatamente após o usuário iniciar o aplicativo. Quando o aplicativo está 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 classe SplashScreen para implementar uma tela inicial. Para obter mais informações, consulte Adicionar uma tela inicial a um aplicativo WPF.
Você também pode implementar sua própria tela inicial usando gráficos Win32 nativos. Exiba sua implementação antes que o método Run seja chamado.
Analise o código de inicialização
Determine o motivo de uma inicialização lenta a frio. O Input/Output de disco pode ser responsável, mas isso nem sempre acontece. Em geral, você deve minimizar o uso de recursos externos, como rede, serviços Web ou disco.
Antes de testar, verifique se nenhum outro aplicativo ou serviço em execução usa código gerenciado ou código WPF.
Inicie seu aplicativo WPF imediatamente após uma reinicialização e determine quanto tempo leva para exibir. Se todos os lançamentos subsequentes do seu aplicativo (inicialização quente) forem muito mais rápidos, seu problema de inicialização a frio provavelmente será causado por E/S.
Se o problema de inicialização a frio do seu aplicativo não estiver relacionado à E/S, é provável que seu aplicativo execute alguma inicialização ou computação demorada, aguarde a conclusão de algum evento ou exija muita compilação JIT na inicialização. As seções a seguir descrevem algumas dessas situações com mais detalhes.
Otimizar o carregamento do módulo
Use ferramentas como Process Explorer (Procexp.exe) e Tlist.exe para determinar quais módulos seu aplicativo carrega. O comando Tlist <pid>
mostra todos os módulos que são carregados por um processo.
Por exemplo, se não estiveres a ligar-te à Web e vires que System.Web.dll está carregado, então existe um módulo na tua aplicação que refere este assembly. Verifique se a referência é necessária.
Se seu aplicativo tiver vários módulos, mescle-os em um único módulo. Essa abordagem requer menos sobrecarga de carregamento de montagem CLR. Menos assemblies também significam que o CLR mantém menos estado.
Adiar operações de inicialização
Considere adiar o código de inicialização até que a janela principal do aplicativo seja renderizada.
Lembre-se de que a inicialização pode ser executada dentro de um construtor de classe e, se o código de inicialização fizer referência a outras classes, ele pode causar um efeito em cascata no qual muitos construtores de classe são executados.
Evite a configuração do aplicativo
Considere evitar a configuração do aplicativo. Por exemplo, se um aplicativo tiver requisitos de configuração simples e tiver metas rígidas de tempo de inicialização, as entradas do Registro ou um arquivo INI simples podem ser uma alternativa de inicialização mais rápida.
Utilize o GAC
Se um assembly não estiver instalado na Global Assembly Cache (GAC), podem ocorrer atrasos devido à verificação de hash de assemblies com nome forte e à validação da imagem Ngen, caso uma imagem nativa para esse assembly esteja disponível no computador. A verificação de nome forte é ignorada para todos os conjuntos instalados no GAC. Para obter mais informações, consulte Gacutil.exe (Global Assembly Cache Tool).
Utilize Ngen.exe
Considere usar o Native Image Generator (Ngen.exe) em seu aplicativo. Usar Ngen.exe significa trocar o consumo da CPU por mais acesso ao disco, porque a imagem nativa gerada pelo Ngen.exe provavelmente será maior do que a imagem MSIL.
Para melhorar o tempo de inicialização quente, você deve sempre usar Ngen.exe em seu aplicativo, porque isso evita o custo da CPU da compilação JIT do código do aplicativo.
Em alguns cenários de inicialização a frio, usar Ngen.exe também pode ser útil. Isso ocorre porque o compilador JIT (mscorjit.dll) não precisa ser carregado.
Ter módulos Ngen e JIT pode ter o pior efeito. Isso ocorre porque mscorjit.dll deve ser carregado, e, quando o compilador JIT compila o 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 a diferença no tempo de carregamento. A implantação do aplicativo ClickOnce não suporta Ngen. Se você decidir usar Ngen.exe para seu aplicativo, terá que usar outro mecanismo de implantação, como o Windows Installer.
Para obter mais informações, consulte Ngen.exe (Native Image Generator).
Realocação de base e colisões de endereço DLL
Se você usar Ngen.exe, esteja ciente de que a rebase pode ocorrer quando as imagens nativas são carregadas na memória. Se uma DLL não for carregada em seu endereço base preferido porque esse intervalo de endereços já está alocado, o carregador do Windows a carregará em outro endereço, o que pode ser uma operação demorada.
Você pode usar a ferramenta Virtual Address Dump (Vadump.exe) para verificar se há módulos nos quais todas as páginas são privadas. Se este for o caso, o módulo pode ter sido rebaseado 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 base, consulte Ngen.exe (Native Image Generator).
Otimizar o Authenticode
A verificação do Authenticode aumenta o tempo de inicialização. Os conjuntos assinados com autenticode devem ser verificados com uma autoridade de certificação (CA). Essa verificação pode ser demorada, pois pode exigir a conexão à rede várias vezes para baixar as listas de revogação de certificados atuais. Ele também garante que haja uma cadeia completa de certificados válidos no caminho para uma raiz confiável. Isso pode se traduzir em vários segundos de atraso enquanto o assembly está sendo carregado.
Considere instalar o certificado de autoridade de certificação no computador cliente ou evite usar o Authenticode quando for possível. Se souber que a sua candidatura não necessita de provas do editor, não tem de pagar o custo da verificação da 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 ao arquivo app.exe.config:
<configuration>
<runtime>
<generatePublisherEvidence enabled="false"/>
</runtime>
</configuration>
Para obter mais informações, consulte <generatePublisherEvidence> Elemento.
Compare 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 trabalha 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 dados na memória sem analisar padrões de uso. Com o tempo, se o usuário usa seu aplicativo WPF com freqüência no Windows Vista, o tempo de inicialização a frio do seu aplicativo pode melhorar.
Utilize AppDomains de forma eficiente
Se possível, carregue assemblies em uma área de código neutro de domínio para garantir que a imagem nativa, se existir, seja usada em todos os AppDomains criados no aplicativo.
Para obter o melhor desempenho, imponha uma comunicação eficiente entre domínios reduzindo as chamadas entre domínios. Sempre que 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 malsucedidas de bibliotecas de código.
Usar o Gerador de Serializador XML
Se usar a classe XmlSerializer, poderá obter um melhor desempenho se pré-gerar o assembly de serialização usando a ferramenta XML Serializer Generator (Sgen.exe).
Configurar o ClickOnce para verificar se há atualizações após a inicialização
Se seu aplicativo usa ClickOnce, evite o acesso à rede na inicialização configurando o ClickOnce para verificar se há atualizações no site de implantação depois que o aplicativo for iniciado.
Se você usar o modelo de aplicativo de navegador XAML (XBAP), 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 ClickOnce Security and Deployment.
Advertência
Os XBAPs requerem navegadores herdados para funcionar, como o Internet Explorer e versões antigas do Firefox. Esses navegadores mais antigos geralmente não são suportados no Windows 10 e no 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 freqüentes sobre aplicativos hospedados no navegador WPF (XBAP).
Configurar o serviço PresentationFontCache para iniciar automaticamente
O primeiro aplicativo WPF a ser executado após uma reinicialização é o serviço PresentationFontCache. O serviço armazena em cache as fontes do sistema, melhora o acesso às fontes e melhora o desempenho geral. Há uma sobrecarga ao iniciar o serviço e, em alguns ambientes controlados, considere configurar o serviço para iniciar automaticamente quando o sistema for reinicializado.
Definir vinculação de dados programaticamente
Em vez de usar XAML para definir o DataContext declarativamente para a janela principal, considere defini-lo programaticamente no método OnActivated.
Ver também
.NET Desktop feedback