Compartir a través de


Consideraciones de rendimiento para la interoperabilidad (C++)

En este tema se proporcionan instrucciones para reducir el efecto de las transiciones de interoperabilidad administradas o no administradas en el rendimiento del entorno de ejecución.

Visual C++ admite los mismos mecanismos de interoperabilidad que otros lenguajes .NET, como Visual Basic y C# (P/Invoke), pero también proporciona compatibilidad de interoperabilidad específica para Visual C++ (interoperabilidad de C++). En el caso de las aplicaciones críticas para el rendimiento, es importante comprender las implicaciones de rendimiento de cada técnica de interoperabilidad.

Independientemente de la técnica de interoperabilidad usada, se requieren secuencias de transición especiales, denominadas código thunk, cada vez que una función administrada llama a una función no administrada y viceversa. El compilador de Microsoft C++ inserta automáticamente este código thunk, pero es importante tener en cuenta que, de forma acumulativa, estas transiciones pueden ser costosas en términos de rendimiento.

Reducción de transiciones

Una manera de evitar o reducir el costo del código thunk de interoperabilidad es refactorizar las interfaces implicadas para minimizar las transiciones administradas o no administradas. Es posible mejorar drásticamente el rendimiento centrando las acciones en las interfaces locuaces, que son las que implican llamadas frecuentes a través de la frontera entre lo administrado y lo no administrado. Una función administrada que llama a una función no administrada en un bucle ajustado, por ejemplo, es una buena candidata para la refactorización. Si el propio bucle se traslada al lado no administrado, o si se crea una alternativa administrada a la llamada no administrada (tal vez poniendo en cola los datos en el lado administrado y luego serializándolos a la API no administrada de una sola vez después del bucle), el número de transiciones puede reducirse significativamente.

Interoperabilidad de P/Invoke frente a C++

En el caso de los lenguajes .NET, como Visual Basic y C#, el método prescrito para interoperar con componentes nativos es P/Invoke. Dado que P/Invoke también es compatible con .NET Framework, Visual C++ también lo admite, pero Visual C++ también proporciona su propia compatibilidad con la interoperabilidad, que se conoce como interoperabilidad de C++. La interoperabilidad de C++ se prefiere sobre P/Invoke porque P/Invoke no tiene seguridad de tipos. Como resultado, los errores se notifican principalmente en el entorno de ejecución, pero la interoperabilidad de C++ también tiene ventajas de rendimiento sobre P/Invoke.

Ambas técnicas requieren que se produzcan varias cosas cada vez que una función administrada llama a una función no administrada:

  • Los argumentos de la llamada de función se serializarán de CLR a tipos nativos.

  • Se ejecuta un thunk administrado a no administrado.

  • Se llama a la función no administrada (mediante las versiones nativas de los argumentos).

  • Se ejecuta un thunk no administrado a administrado.

  • El tipo de valor devuelto y los argumentos "out" o "in,out" se serializarán de tipos nativos a CLR.

Los thunks administrados o no administrados son necesarios para que la interoperabilidad funcione, pero la serialización de datos necesaria depende de los tipos de datos implicados, la firma de función y cómo se usarán los datos.

La serialización de datos realizada por la interoperabilidad de C++ es la forma más sencilla posible: los parámetros se copian simplemente a través del límite administrado o no administrado de forma bit a bit; no se realiza ninguna transformación. Para P/Invoke, esto solo se cumple si todos los parámetros son tipos simples y pueden transferirse en bloque de bits. De lo contrario, P/Invoke realiza pasos muy eficaces para convertir cada parámetro administrado en un tipo nativo adecuado y viceversa si los argumentos se marcan como "out" o "in,out".

En otras palabras, la interoperabilidad de C++ usa el método más rápido posible de serialización de datos, mientras que P/Invoke usa el método más eficaz. Esto significa que la interoperabilidad de C++ (de forma típica para C++) proporciona un rendimiento óptimo de forma predeterminada, y el programador es responsable de abordar los casos en los que este comportamiento no es seguro o adecuado.

Por lo tanto, la interoperabilidad de C++ requiere que la serialización de datos se proporcione explícitamente, pero la ventaja es que el programador tiene la libertad de decidir qué es adecuado, dada la naturaleza de los datos, y cómo se va a usar. Además, aunque el comportamiento de la serialización de datos de P/Invoke se puede modificar hasta cierto punto, la interoperabilidad de C++ permite personalizar la serialización de datos llamada a llamada. Esto no es posible con P/Invoke.

Para obtener más información sobre la interoperabilidad de C++, consulte Utilizar la interoperabilidad de C++ (PInvoke implícito).

Consulte también

Ensamblados mixtos (nativos y administrados)