Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Crie aplicativos do Windows que usam componentes do Tempo de Execução do Windows e interoperem entre tipos nativos e gerenciados, evitando problemas de desempenho de interoperabilidade.
Práticas recomendadas para interoperabilidade com componentes do Tempo de Execução do Windows
Se você não tiver cuidado, usar os Componentes do Tempo de Execução do Windows pode ter um grande impacto no desempenho do seu aplicativo. Esta seção discute como obter um bom desempenho quando seu aplicativo usa componentes do Tempo de Execução do Windows.
Introdução
A interoperabilidade pode ter um grande impacto no desempenho e você pode estar usando-a sem nem perceber que está. O Tempo de Execução do Windows lida com grande parte da interoperabilidade para que você possa ser mais produtivo e reutilizar o código que foi escrito em outros idiomas. Recomendamos que você aproveite o que o Tempo de Execução do Windows faz por você, mas esteja ciente de que isso pode afetar o desempenho. Esta seção discute as coisas que você pode fazer para diminuir o impacto que a interoperabilidade tem no desempenho do seu aplicativo.
O Windows Runtime tem uma biblioteca de tipos acessíveis a partir de qualquer linguagem que possa escrever uma aplicação da Plataforma Universal do Windows. Você usa os tipos do Tempo de Execução do Windows em C# ou Microsoft Visual Basic da mesma forma que usa objetos .NET. Não é necessário fazer chamadas de método de invocação de plataforma para acessar os componentes do Tempo de Execução do Windows. Isso torna a escrita de seus aplicativos muito menos complexa, mas é importante perceber que pode haver mais interoperabilidade ocorrendo do que você espera. Se um componente do Tempo de Execução do Windows for escrito em uma linguagem diferente de C# ou Visual Basic, você cruzará os limites de interoperabilidade ao usar esse componente. Cruzar os limites de interoperabilidade pode afetar o desempenho de um aplicativo.
Quando você desenvolve um aplicativo da Plataforma Universal do Windows em C# ou Visual Basic, os dois conjuntos mais comuns de APIs que você usa são as APIs do Tempo de Execução do Windows e as APIs do .NET para aplicativos UWP. Em geral, os tipos fornecidos pelo Windows que são criados no Tempo de Execução do Windows em namespaces que começam com "Windows." e tipos .NET estão em namespaces que começam com "Sistema". No entanto, há exceções. Os tipos no .NET para aplicativos UWP não exigem interoperabilidade quando são usados. Se você achar que tem um desempenho ruim em uma área que usa o Tempo de Execução do Windows, poderá usar o .NET para aplicativos UWP em vez disso para obter um melhor desempenho.
Observação A maioria dos componentes do Tempo de Execução do Windows fornecidos com o Windows 10 são implementados em C++ para que você cruze os limites de interoperabilidade ao usá-los em C# ou Visual Basic. Como sempre, certifique-se de medir seu aplicativo para ver se o uso de componentes do Tempo de Execução do Windows afeta o desempenho do aplicativo antes de investir em fazer alterações no código.
Neste tópico, quando mencionamos "componentes do Tempo de Execução do Windows", queremos dizer Componentes do Tempo de Execução do Windows escritos em uma linguagem diferente de C# ou Visual Basic.
Cada vez que você acessa uma propriedade ou chama um método em um componente do Tempo de Execução do Windows, um custo de interoperabilidade é incorrido. Na verdade, criar um componente do Tempo de Execução do Windows é mais caro do que criar um objeto .NET. Os motivos para isso são que o Tempo de Execução do Windows deve executar código que faz a transição do idioma do seu aplicativo para o idioma do componente. Além disso, se você passar dados para o componente, os dados deverão ser convertidos entre os tipos gerenciado e não gerenciado.
Usando componentes do Tempo de Execução do Windows de forma eficiente
Se você achar que precisa obter um melhor desempenho, poderá garantir que seu código use componentes do Tempo de Execução do Windows da forma mais eficiente possível. Esta seção discute algumas dicas para melhorar o desempenho quando você usa componentes do Tempo de Execução do Windows.
É necessário um número significativo de chamadas num curto período de tempo para que o impacto no desempenho seja percetível. Uma aplicação bem projetada que encapsula chamadas para componentes do Windows Runtime a partir da lógica de negócios e de outro código gerido não deve incorrer em grandes custos de interoperabilidade. Mas se os testes indicarem que o uso de componentes do Tempo de Execução do Windows está afetando o desempenho do seu aplicativo, as dicas discutidas nesta seção ajudarão você a melhorar o desempenho.
Considere o uso de tipos fornecidos pelo .NET para aplicativos UWP
Há certos casos em que você pode realizar uma tarefa usando o tipo do Tempo de Execução do Windows ou um tipo fornecido pelo .NET para aplicativos UWP. É uma boa ideia tentar não misturar tipos .NET e tipos do Tempo de Execução do Windows. Tente ficar em um ou outro. Por exemplo, é possível analisar um fluxo XML utilizando o tipo Windows.Data.Xml.Dom.XmlDocument (um tipo do Windows Runtime) ou o tipo System.Xml.XmlReader (um tipo .NET). Use a API que é da mesma tecnologia que o fluxo. Por exemplo, se você ler xml de um MemoryStream, use o tipo de System.Xml.XmlReader, porque ambos os tipos são tipos .NET. Se você ler a partir de um arquivo, use o tipo de Windows.Data.Xml.Dom.XmlDocument porque as APIs de arquivo e XmlDocument são implementadas em componentes nativos do Tempo de Execução do Windows.
Copiar objetos do Window Runtime para tipos .NET
Quando um componente do Tempo de Execução do Windows retorna um objeto do Tempo de Execução do Windows, pode ser benéfico copiar o objeto retornado para um objeto .NET. Dois lugares onde isso é especialmente importante é quando você está trabalhando com coleções e fluxos.
Se você chamar uma API do Tempo de Execução do Windows que retorna uma coleção e, em seguida, salvar e acessar essa coleção muitas vezes, pode ser benéfico copiar a coleção para uma coleção .NET e usar a versão .NET a partir de então.
Armazenar em cache os resultados de chamadas para componentes do Tempo de Execução do Windows para uso posterior
Talvez você consiga obter um melhor desempenho salvando valores em variáveis locais em vez de acessar um tipo de Tempo de Execução do Windows várias vezes. Isso pode ser especialmente benéfico se você usar um valor dentro de um loop. Meça seu aplicativo para ver se o uso de variáveis locais melhora o desempenho do aplicativo. O uso de valores armazenados em cache pode aumentar a velocidade do seu aplicativo porque ele gastará menos tempo com interoperabilidade.
Combinar chamadas para componentes do Tempo de Execução do Windows
Tente concluir tarefas com o menor número possível de chamadas para objetos UWP. Por exemplo, geralmente é melhor ler uma grande quantidade de dados de um fluxo do que ler pequenas quantidades de cada vez.
Use APIs que agrupam o trabalho no menor número possível de chamadas, em vez de APIs que fazem menos trabalho e exigem mais chamadas. Por exemplo, prefira criar um objeto chamando construtores que inicializam várias propriedades uma vez em vez de chamar o construtor padrão e atribuir propriedades uma de cada vez.
Construindo componentes do Windows Runtime
Se você escrever um componente do Tempo de Execução do Windows que possa ser usado por aplicativos escritos em C++ ou JavaScript, certifique-se de que seu componente foi projetado para um bom desempenho. Todas as sugestões para obter um bom desempenho em aplicativos se aplicam a obter um bom desempenho em componentes. Meça seu componente para descobrir quais APIs têm altos padrões de tráfego e, para essas áreas, considere fornecer APIs que permitam que seus usuários trabalhem com poucas chamadas.
Mantenha seu aplicativo rápido quando você usa interoperabilidade em código gerenciado
O Tempo de Execução do Windows facilita a interoperação entre código nativo e gerenciado, mas, se você não tiver cuidado, pode incorrer em custos de desempenho. Aqui mostramos como obter um bom desempenho quando você usa interoperabilidade em seus aplicativos UWP gerenciados.
O Widows Runtime permite que os desenvolvedores escrevam aplicativos usando XAML com a linguagem de sua escolha, graças às projeções das APIs do Tempo de Execução do Windows disponíveis em cada idioma. Ao desenvolver um aplicativo em C# ou Visual Basic, há um custo de interoperabilidade devido às conveniências oferecidas, porque as APIs do Windows Runtime normalmente são implementadas em código nativo. Qualquer invocação do Windows Runtime a partir de C# ou Visual Basic exige que o CLR faça a transição de um frame de pilha gerenciado para um frame de pilha nativo e converta os parâmetros de funções para formatos acessíveis por código nativo. Essa sobrecarga é insignificante para a maioria dos aplicativos. Mas quando se fazem muitas chamadas (de centenas de milhares a milhões) para Windows Runtime APIs no caminho crítico de um aplicativo, esse custo pode se tornar percetível. Em geral, você deseja garantir que o tempo gasto na transição entre idiomas seja pequeno em relação à execução do restante do código. Isto é ilustrado pelo diagrama a seguir.
Os tipos listados em .NET para aplicativos do Windows não incorrem nesse custo de interoperabilidade quando usados em C# ou Visual Basic. Como regra geral, pode-se assumir que tipos de namespaces que começam com "Windows". fazem parte do conjunto de APIs do Windows Runtime fornecido pelo Windows e tipos em namespaces que começam com "System." são tipos .NET. Lembre-se de que mesmo o uso simples de tipos do Tempo de Execução do Windows incorre em um custo de interoperabilidade para alocação ou acesso à propriedade.
Você deve medir seu aplicativo e determinar se a interoperabilidade está ocupando uma grande parte do tempo de execução de seus aplicativos antes de otimizar seus custos de interoperabilidade. Ao analisar o desempenho da sua aplicação com o Visual Studio, pode obter facilmente um limite superior para os custos de interoperabilidade utilizando a vista Functions e observando o tempo inclusivo gasto em métodos que chamam o Windows Runtime.
Se o seu aplicativo estiver lento devido à sobrecarga de interoperabilidade, você pode melhorar o seu desempenho reduzindo as chamadas para Windows Runtime APIs em caminhos críticos de código. Por exemplo, um mecanismo de jogo que está fazendo toneladas de cálculos físicos consultando constantemente a posição e as dimensões de UIElements pode economizar muito tempo armazenando as informações necessárias de UIElements para variáveis locais, fazendo cálculos nesses valores armazenados em cache e atribuindo o resultado final de volta ao UIElements depois que os cálculos são feitos. Outro exemplo: se uma coleção for fortemente acessada por código C# ou Visual Basic, será mais eficiente usar uma coleção do namespace System.Collections em vez de uma coleção do namespace Windows.Foundation.Collections . Você também pode considerar a combinação de chamadas para componentes do Tempo de Execução do Windows; um exemplo em que isso é possível é usando o Windows.Storage.BulkAccess APIs.
Criando um componente UWP
Se você escrever um componente do Tempo de Execução do Windows para uso em aplicativos escritos em C++ ou JavaScript, verifique se o componente foi projetado para um bom desempenho. Sua superfície de API define seu limite de interoperabilidade e define o grau em que seus usuários terão que pensar sobre as diretrizes neste tópico. Se você estiver distribuindo seus componentes para outras partes, isso se torna especialmente importante.
Todas as sugestões para obter um bom desempenho em aplicativos se aplicam à obtenção de um bom desempenho em componentes. Meça seu componente para descobrir quais APIs têm altos padrões de tráfego e, para essas áreas, considere fornecer APIs que permitam que seus usuários trabalhem com poucas chamadas. Foi feito um esforço significativo na conceção do Tempo de Execução do Windows para permitir que os aplicativos o usassem sem exigir cruzamento frequente dos limites de interoperabilidade.