Compartir a través de


Información general sobre la generación de perfiles

Un generador de perfiles es una herramienta que supervisa la ejecución de otra aplicación. Un generador de perfiles de Common Language Runtime (CLR) es una biblioteca de vínculos dinámicos (DLL) compuesta de funciones que intercambian mensajes con el CLR utilizando la API de generación de perfiles. CLR carga en tiempo de ejecución la DLL del generador de perfiles.

Las herramientas tradicionales de generación de perfiles se centran en medir la ejecución de la aplicación. Es decir, miden el tiempo que se emplea en cada función o la utilización de memoria de la aplicación a lo largo del tiempo. La API de generación de perfiles se dirige a una clase más amplia de herramientas de diagnóstico tales como las utilidades de cobertura de código e, incluso, las ayudas de depuración avanzadas. Estos usos son diagnósticos por su naturaleza. La API de generación de perfiles no solamente mide, sino que también supervisa la ejecución de una aplicación. Por este motivo, la API de generación de perfiles nunca debe ser utilizada por la propia aplicación, y la ejecución de la aplicación no debe depender del generador de perfiles ni verse afectada por él.

La generación de perfil para una aplicación CLR requiere más soporte que la generación de perfil parea código máquina compilado convencionalmente. Esto es porque CLR introduce conceptos tales como los dominios de aplicación, la recolección de elementos no utilizados, el control de excepciones administrado, la compilación Just-In-Time (JIT) de código (conversión del código de lenguaje intermedio de Microsoft, o MSIL, en código máquina nativo), y características similares. Los mecanismos convencionales de generación de perfiles no pueden identificar o proporcionar información útil sobre estas características. La API de generación de perfiles proporciona eficazmente esta información que falta, con efecto mínimo sobre el rendimiento de CLR y de la aplicación para la que se genera el perfil.

La compilación JIT en tiempo de ejecución proporciona buenas oportunidades para la generación de perfiles. La API de generación de perfiles permite a un generador de perfiles cambiar las secuencias de código de MSIL en memoria para una rutina antes de la compilación JIT. De esta manera, el generador de perfiles puede agregar dinámicamente código instrumental a rutinas determinadas que necesiten una investigación más profunda. Aunque este enfoque es posible en escenarios convencionales, es mucho más fácil de implementar para CLR utilizando la API de generación de perfiles.

Esta información general consta de las siguientes secciones:

  • La API de generación de perfiles

  • Características compatibles

  • Subprocesos de notificación

  • Seguridad

  • Combinar código administrado y no administrado en un generador de perfiles de código

  • Código no administrado de generación de perfiles

  • Utilizar COM

  • Pilas de llamadas

  • Devoluciones de llamada y profundidad de la pila

  • Temas relacionados

La API de generación de perfiles

Normalmente, la API de generación de perfiles se utiliza para escribir un generador de perfiles de código, que es un programa que supervisa la ejecución de una aplicación administrada.

La API de generación de perfiles la utiliza una DLL de generación de perfiles, que se carga en el mismo proceso que la aplicación para la que se está generando el perfil. La DLL del generador de perfiles implementa una interfaz de devolución de llamada (ICorProfilerCallback en las versiones 1.0 y 1.1 de .NET Framework, ICorProfilerCallback2 en las versiones 2.0 y posteriores). CLR llama a los métodos de esa interfaz para notificar al generador de perfiles eventos en el proceso perfilado. El generador de perfiles puede devolver la llamada en tiempo de ejecución utilizando los métodos de las interfaces ICorProfilerInfo e ICorProfilerInfo2 para obtener información sobre el estado de la aplicación para la que se genera el perfil.

NotaNota

Sólo la parte de recolección de datos de la solución del generador de perfiles debe estar en ejecución en el mismo proceso que la aplicación para la que se genera el perfil.Toda la interfaz de usuario y el análisis de datos se deben ejecutar en un proceso independiente.

La ilustración siguiente muestra cómo interactúa la DLL del generador de perfiles con la aplicación para la que se está generando el perfil y CLR.

Arquitectura de generación de perfiles

Arquitectura de generación de perfiles

Las interfaces de notificación

ICorProfilerCallback e ICorProfilerCallback2 pueden considerarse interfaces de notificación. Estas interfaces constan de métodos tales como ClassLoadStarted, ClassLoadFinishedy JITCompilationStarted. Cada vez que CLR carga o descarga una clase, compila una función, etc., llama al método correspondiente de la interfaz ICorProfilerCallback o ICorProfilerCallback2 del generador de perfiles.

Por ejemplo, un generador de perfiles puede medir el rendimiento del código a través de dos funciones de notificación: FunctionEnter2 y FunctionLeave2. Simplemente marca el tiempo de cada notificación, acumula los resultados y genera una lista que indica qué funciones consumieron la mayoría del tiempo de CPU o de reloj durante la ejecución de la aplicación.

Las interfaces de recuperación de información

Las otras interfaces principales implicadas en la generación de perfiles son ICorProfilerInfo e ICorProfilerInfo2. El generador de perfiles llama a estas interfaces según es necesario para obtener más información como ayuda para su análisis. Por ejemplo, cada vez que CLR llama a la función FunctionEnter2, proporciona un identificador de función. El generador de perfiles puede obtener más información sobre esa función llamando al método ICorProfilerInfo2::GetFunctionInfo2 para detectar la clase primaria de la función, su nombre, etc.

Volver al principio

Características compatibles

La API de generación de perfiles proporciona información sobre diversos eventos y acciones que se producen en Common Language Runtime. Puede usar esta información para supervisar los mecanismos internos de los procesos y para analizar el rendimiento de la aplicación .NET Framework.

La API de generación de perfiles recupera información sobre los siguientes eventos y acciones que se producen en el CLR:

  • Eventos de inicio y cierre de CLR.

  • Eventos de creación y cierre de dominio de aplicación.

  • Eventos de carga y descarga de ensamblados.

  • Eventos de carga y descarga de módulos.

  • Eventos de creación y destrucción de vtable COM.

  • Eventos de compilación Just-In-Time (JIT) y eliminación de código nativo.

  • Eventos de carga y descarga de clase.

  • Eventos de creación y destrucción de subprocesos.

  • Eventos de entrada y salida de función.

  • Excepciones.

  • Transiciones entre la ejecución de código administrado y no administrado.

  • Transiciones entre diferentes contextos de tiempo de ejecución.

  • Información sobre suspensiones de tiempo de ejecución.

  • Información sobre el montón de memoria de tiempo de ejecución y la actividad de recolección de elementos no utilizados.

Se puede llamar a la API de generación de perfiles desde cualquier lenguaje compatible con COM (no administrado).

La API es eficaz con respecto a CPU y al consumo de memoria. La generación de perfiles no implica cambios en la aplicación para la que se genera el perfil que sean lo bastante significativos como para producir resultados engañosos.

La API de generación de perfiles es útil tanto para los generadores de perfiles de muestreo como no de muestreo. Un generador de perfiles de muestreo inspecciona el perfil a intervalos regulares del reloj de, digamos, 5 milisegundos. Un generador de perfiles de no muestreo se informa sincrónicamente de un evento con el subproceso que produce el evento.

Funcionalidad incompatible

La API de generación de perfiles no admite la funcionalidad siguiente:

  • Código no administrado, que se debe perfilar usando métodos de Win32 convencionales. Sin embargo, el generador de perfiles de CLR incluye eventos de transición para determinar los límites entre el código administrado y no administrado.

  • Aplicaciones que modifican su propio código para propósitos tales como la programación orientada a aspectos.

  • Comprobación de límites, ya que la API de generación de perfiles no proporciona esta información. CLR proporciona compatibilidad intrínseca para la comprobación de límites de todo el código administrado.

  • Generación de perfiles remota, que no se admite por las siguientes razones:

    • La generación remota de perfiles prolonga el tiempo de ejecución. Cuando usa las interfaces de generación de perfiles, debe minimizar el tiempo de ejecución de modo que los resultados de la generación de perfiles no se vean excesivamente afectados. Esto es especialmente cierto cuando se supervisa el rendimiento de la ejecución. Sin embargo, la generación remota de perfiles no es una limitación cuando las interfaces de generación de perfiles se emplean para supervisar el uso de memoria o para obtener información en tiempo de ejecución sobre marcos de pila, objetos, etc.

    • El generador de perfiles del código de CLR debe registrar una o más interfaces de devolución de llamada con el motor en tiempo de ejecución en el equipo local en el que se está ejecutando la aplicación para la que se genera el perfil. Esto limita la capacidad para crear un generador de perfiles de código remoto.

  • Generación de perfiles en entornos de producción con requisitos de alta disponibilidad. La API de generación de perfiles fue creada para admitir diagnósticos en tiempo de desarrollo. No se ha sometido a las rigurosas pruebas exigidas para la compatibilidad de entornos de producción.

Volver al principio

Subprocesos de notificación

En la mayoría de los casos, el subproceso que genera un evento ejecuta también las notificaciones. Tales notificaciones (por ejemplo, FunctionEnter y FunctionLeave) no necesitan proporcionar el ThreadIDexplícito. Además, el generador de perfiles puede decidir utilizar almacenamiento local de subproceso para almacenar y actualizar sus bloques de análisis, en lugar de indizar los bloques de análisis en almacenamiento global, en función del ThreadID del subproceso afectado.

Tenga en cuenta que estas devoluciones de llamada no se serializan. Los usuarios deben proteger su código creando estructuras de datos seguras para subprocesos y bloqueando el código del generador de perfiles donde sea necesario para evitar el acceso paralelo desde varios subprocesos. Por consiguiente, en ciertos casos puede recibir una secuencia poco habitual de devoluciones de llamada. Por ejemplo, suponga que una aplicación administrada está generando dos subprocesos que está ejecutando código idéntico. En este caso, es posible recibir un evento ICorProfilerCallback::JITCompilationStarted para alguna función de un subproceso y una devolución de llamada FunctionEnter del otro subproceso antes de recibir la devolución de llamada ICorProfilerCallback::JITCompilationFinished. En este caso, el usuario recibirá una devolución de llamada FunctionEnter para una función que puede no haberse compilado totalmente Just-In-Time (JIT) todavía.

Volver al principio

Seguridad

Una DLL del generador de perfiles es una DLL no administrada que se ejecuta como parte del motor de ejecución de Common Language Runtime. Como resultado, el código de la DLL del generador de perfiles no está sujeto a las restricciones de seguridad de acceso del código administrado. Las únicas limitaciones sobre la DLL del generador de perfiles son las impuestas por el sistema operativo sobre el usuario que está ejecutando la aplicación para la que se ha generado el perfil.

Los autores del generador de perfiles deben tomar las precauciones adecuadas para evitar problemas relacionados con la seguridad. Por ejemplo, durante la instalación, la DLL del generador de perfiles debe agregarse a una lista de control de acceso (ACL) para que los usuarios malintencionados no puedan modificarla.

Volver al principio

Combinar código administrado y no administrado en un generador de perfiles de código

Un generador de perfiles incorrectamente escrito puede provocar referencias circulares a sí mismo, produciendo un comportamiento imprevisible.

Una revisión de la API de generación de perfiles de CLR puede crear la impresión de que se puede escribir un generador de perfiles que contenga componentes administrados y no administrados, que de llaman entre sí a través de interoperabilidad COM o llamadas indirectas.

Aunque esto es posible desde la perspectiva del diseño, la API de generación de perfiles no admite componentes administrados. Un generador de perfiles de CLR debe ser completamente no administrado. Los intentos de combinar código administrado y código no administrado en un generador de perfiles de CLR pueden provocar intentos de acceso no permitido, errores de programa o interbloqueos. Los componentes administrados del generador de perfiles devolverán eventos a sus componentes no administrados, que llamarán de nuevo, como consecuencia, a los componentes administrados, produciendo referencias circulares.

La única ubicación donde un generador de perfiles de CLR puede llamar sin ningún riesgo a código administrado es en el cuerpo de un método de lenguaje intermedio de Microsoft (MSIL). Antes de que se complete la compilación Just-In-Time (JIT) de una función, el generador de perfiles puede insertar llamadas administradas en el cuerpo de MSIL de un método y, a continuación, realizar la compilación JIT (vea el método ICorProfilerInfo::GetILFunctionBody ). Esta técnica se puede utilizar con éxito para el instrumental selectivo de código administrado o para recopilar estadísticas y datos de rendimiento sobre JIT.

Como alternativa, un generador de perfiles de código puede insertar enlaces nativos en el cuerpo de MSIL de cada función administrada que llame a código no administrado. Esta técnica se puede utilizar para instrumental y cobertura. Por ejemplo, un generador de perfiles de código puede insertar enlaces de instrumental después de cada bloque de MSIL para asegurarse de que se ha ejecutado el bloque. La modificación del cuerpo MSIL de un método es una operación muy delicada y hay muchos factores que se deben tener en cuenta.

Volver al principio

Código no administrado de generación de perfiles

La API de generación de perfiles de Common Language Runtime (CLR) proporciona la compatibilidad mínima para el código no administrado de generación de perfiles. Se proporciona la funcionalidad siguiente:

  • Enumeración de cadenas de pila. Esta característica permite a un generador de perfiles de código determinar el límite entre el código administrado y el código no administrado.

  • Determinación de si una cadena de pila corresponde a código administrado o código nativo.

En las versiones 1.0 y 1.1 de .NET Framework, estos métodos están disponibles a través del subconjunto en proceso de la API de depuración de CLR. Se definen en el archivo CorDebug.idl y se explican en Información general sobre la depuración en CLR.

En .NET Framework 2.0 y versiones posteriores, puede usar el método ICorProfilerInfo2::DoStackSnapshot para esta funcionalidad.

Volver al principio

Utilizar COM

Aunque las interfaces de generación de perfiles se definen como interfaces COM, Common Language Runtime (CLR) no inicializa realmente COM para utilizar estas interfaces. La razón es evitar tener que establecer el modelo de subprocesos utilizando la función CoInitialize antes de que la aplicación administrada haya tenido una oportunidad para especificar su modelo de subprocesos deseado. De igual forma, el propio generador de perfiles no debe llamar a CoInitialize, porque puede elegir un modelo de subprocesos que sea incompatible con la aplicación para la que se está generando el perfil y puede hacer que la aplicación no funcione correctamente.

Volver al principio

Pilas de llamadas

La API de generación de perfiles proporciona dos maneras de obtener pilas de llamadas: un método de instantánea de pila, que habilita la recolección dispersa de pilas de llamadas, y un método de pila de sombra, que realiza el seguimiento de la pila de llamadas en cada momento.

Instantánea de pila

Una instantánea de pila es un registro de la pila de un subproceso en un momento determinado. La API de generación de perfiles permite la traza de funciones administradas en la pila, pero deja la traza de las funciones no administradas al rastreador de pila propio del generador de perfiles.

Para obtener más información sobre cómo programar el generador de perfiles para rastrear pilas administradas, vea el método ICorProfilerInfo2::DoStackSnapshot en este conjunto de documentación y Profiler Stack Walking in the .NET Framework 2.0: Basics and Beyond en MSDN Library.

Pila sombra

Utilizar el método de instantánea con demasiada frecuencia puede crear rápidamente un problema de rendimiento. Si desea realizar con frecuencia seguimientos de la pila, el generador de perfiles debe compilar en su lugar una pila sombra utilizando las devoluciones de llamada de excepción FunctionEnter2, FunctionLeave2, FunctionTailcall2 e ICorProfilerCallback2. La pila sombra es siempre actual y se copia rápidamente al almacenamiento cada vez que se necesita una instantánea de la pila.

Una pila sombra puede obtener argumentos de función, valores devueltos e información sobre las instancias genéricas. Esta información solamente está disponible a través de la pila sombra y puede obtenerse cuando se entrega el control a una función. Sin embargo, es posible que esta información no esté disponible más tarde, durante la ejecución de la función.

Volver al principio

Devoluciones de llamada y profundidad de la pila

Las devoluciones de llamada del generador de perfiles se pueden emitir en circunstancias muy restringidas por la pila y un desbordamiento de pila en una devolución de llamada del generador de perfiles conducirá a una inmediata salida del proceso. Un generador de perfiles debe asegurarse de usar la mínima pila posible en respuesta a las devoluciones de llamada. Si el generador de perfiles está destinado a usarse contra procesos robustos contra el desbordamiento de pila, el propio generador de perfiles deberá también evitar activar el desbordamiento de pila.

Volver al principio

Temas relacionados

Título

Descripción

Generar perfiles en .NET Framework 2.0

Describe los cambios y las mejoras de la generación de perfiles en .NET Framework 2.0 y en versiones posteriores.

Configurar un entorno de generación de perfiles

Explica cómo inicializar un generador de perfiles, establecer notificaciones de eventos y generar perfiles para un servicio de Windows.

Devoluciones de llamada del cargador en la API de generación de perfiles

Explica las devoluciones de llamada que se emiten para cargar dominios de aplicación, ensamblados, módulos y clases.

Recolección de elementos no utilizados en la API de generación de perfiles

Explica cómo se desencadena, detecta y bloquea la recolección de elementos no utilizados.

Seguimiento de objetos en la API de generación de perfiles

Explica cómo se puede realizar el seguimiento de objetos que se movieron durante la recolección de elementos no utilizados.

Inspección de objetos en la API de generación de perfiles

Explica cómo un generador de perfiles puede utilizar metadatos para obtener información sobre objetos.

Control de excepciones en la API de generación de perfiles

Explica cómo un generador de perfiles puede supervisar eventos de excepción.

Generación de código en la API de generación de perfiles

Describe cómo un generador de perfiles puede controlar la generación de código automática y manual.

Identificadores para notificaciones en tiempo de ejecución y generación de perfiles

Explica los id. de clase, subproceso y dominio de aplicación que Common Language Runtime pasa a los generadores de perfiles.

Convenciones de los métodos de la API de generación de perfiles

Describe los valores devueltos de HRESULT, cómo asignar búferes de retorno para su uso por parte de las API de generación de perfiles y el uso de los parámetros de salida opcionales.

Interfaces para generación de perfiles

Describe las interfaces no administradas que utiliza la API de generación de perfiles.

Funciones estáticas globales para generación de perfiles

Describe las funciones estáticas globales no administradas que utiliza la API de generación de perfiles.

Enumeraciones para generación de perfiles

Describe las enumeraciones no administradas que utiliza la API de generación de perfiles.

Estructuras para generación de perfiles

Describe las estructuras no administradas que utiliza la API de generación de perfiles.

Volver al principio