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.
Este tópico fornece diretrizes para reduzir o efeito das transições de interoperabilidade gerenciadas/não gerenciadas no desempenho em tempo de execução.
O Visual C++ oferece suporte aos mesmos mecanismos de interoperabilidade que outras linguagens .NET, como Visual Basic e C# (P/Invoke), mas também fornece suporte de interoperabilidade específico para Visual C++ (interoperabilidade C++). Para aplicativos críticos de desempenho, é importante entender as implicações de desempenho de cada técnica de interoperabilidade.
Independentemente da técnica de interoperabilidade usada, sequências de transição especiais, chamadas thunks, são necessárias cada vez que uma função gerenciada chama uma função não gerenciada e vice-versa. Esses thunks são inseridos automaticamente pelo compilador Microsoft C++, mas é importante ter em mente que, cumulativamente, essas transições podem ser caras em termos de desempenho.
Reduzindo as transições
Uma maneira de evitar ou reduzir o custo dos thunks de interoperabilidade é refatorar as interfaces envolvidas para minimizar as transições gerenciadas/não gerenciadas. Melhorias significativas de desempenho podem ser feitas ao direcionar interfaces verbosas, que são aquelas que envolvem chamadas frequentes entre os limites de código gerido e não gerido. Uma função gerida que chama uma função não gerida num ciclo apertado, por exemplo, é um bom candidato para refatoração. Se o próprio loop for movido para o lado não gerenciado, ou se uma alternativa gerenciada para a chamada não gerenciada for criada (como, por exemplo, enfileirar dados no lado gerenciado e depois transferi-los de uma só vez para a API não gerenciada após o loop), o número de transições pode ser reduzido significativamente.
P/Invoke vs. Interoperabilidade C++
Para linguagens .NET, como Visual Basic e C#, o método prescrito para interoperar com componentes nativos é P/Invoke. Como P/Invoke é suportado pelo .NET Framework, o Visual C++ também oferece suporte a ele, mas o Visual C++ também fornece seu próprio suporte de interoperabilidade, que é conhecido como Interoperabilidade C++. A interoperabilidade C++ é preferível a P/Invoke porque P/Invoke não é seguro para digitação. Como resultado, os erros são relatados principalmente em tempo de execução, mas o C++ Interop também tem vantagens de desempenho sobre P/Invoke.
Ambas as técnicas exigem que várias coisas aconteçam sempre que uma função gerenciada chama uma função não gerenciada:
Os argumentos de chamada de função são convertidos do CLR para tipos nativos.
Um thunk gerenciado para não gerenciado é executado.
A função não gerenciada é chamada (usando as versões nativas dos argumentos).
Um thunk não gerenciado para gerenciado é executado.
O tipo de retorno e quaisquer argumentos "out" ou "in,out" são convertidos de tipos nativos para tipos CLR.
Os thunks geridos/não geridos são necessários para que a interoperabilidade funcione, mas a organização de dados necessária depende dos tipos de dados envolvidos, da assinatura da função e de como os dados serão utilizados.
O marshaling de dados realizado pelo C++ Interop é a forma mais simples possível: os parâmetros são simplesmente copiados através do limite gerenciado/não gerenciado de forma bitwise; nenhuma transformação é realizada. Para P/Invoke, isso só é verdadeiro se todos os parâmetros forem tipos simples e blittable. Caso contrário, P/Invoke executa etapas muito robustas para converter cada parâmetro gerido num tipo nativo apropriado e vice-versa se os argumentos estiverem marcados como "out" ou "in,out".
Em outras palavras, o C++ Interop usa o método mais rápido possível de marshaling de dados, enquanto P/Invoke usa o método mais robusto. Isso significa que a Interoperabilidade C++ (de uma forma típica para C++) fornece desempenho ideal por padrão, e o programador é responsável por abordar casos em que esse comportamento não é seguro ou apropriado.
A Interoperabilidade C++ exige, portanto, que o marshaling de dados seja fornecido explicitamente, mas a vantagem é que o programador é livre para decidir o que é apropriado, dada a natureza dos dados e como serão usados. Além disso, embora o comportamento do marshaling de dados P/Invoke possa ser modificado de maneira personalizada até um determinado ponto, o C++ Interop permite que o marshaling de dados seja ajustado em cada chamada individualmente. Isso não é possível com P/Invoke.
Para obter mais informações sobre interoperabilidade C++, consulte Usando interoperabilidade C++ (PInvoke implícito).