2011-04-02 15 views
8

Estoy tratando de perfilar mi aplicación para controlar los efectos de una función, tanto antes como después de la refactorización. Realicé un análisis de mi aplicación y, tras consultar el Resumen, me di cuenta de que la lista Hot Path no menciona ninguna de mis funciones utilizadas, solo menciona funciones hasta Application.Run()Problemas de creación de perfiles de funciones: Visual Studio 2010 Ultimate

Soy bastante nuevo en la creación de perfiles y me gustaría saber cómo puedo obtener más información sobre Hot Path como se demostró a través del MSDN documentation;

MSDN Ejemplo:

MSDN Example

palmarés:

Hot Path Summary

me he dado cuenta en la ventana de salida hay una gran cantidad de mensajes relacionados con un fracaso al cargar símbolos, algunos de ellos están debajo;

Failed to load symbols for C:\Windows\system32\USP10.dll. 
Failed to load symbols for C:\Windows\system32\CRYPTSP.dll. 
Failed to load symbols for (Omitted)\WindowsFormsApplication1\bin\Debug\System.Data.SQLite.dll. 
Failed to load symbols for C:\Windows\system32\GDI32.dll. 
Failed to load symbols for C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.7601.17514_none_41e6975e2bd6f2b2\comctl32.dll. 
Failed to load symbols for C:\Windows\system32\msvcrt.dll. 
Failed to load symbols for C:\Windows\Microsoft.NET\Framework\v4.0.30319\nlssorting.dll. 
Failed to load symbols for C:\Windows\Microsoft.Net\assembly\GAC_32\System.Data\v4.0_4.0.0.0__b77a5c561934e089\System.Data.dll. Failed to load symbols for 
C:\Windows\Microsoft.Net\assembly\GAC_32\System.Transactions\v4.0_4.0.0.0__b77a5c561934e089\System.Transactions.dll. 
Unable to open file to serialize symbols: Error VSP1737: File could not be opened due to sharing violation: - D:\(Omitted)\WindowsFormsApplication1110402.vsp 

(formato utilizando la herramienta de código por lo que es legible)

Gracias por cualquier punteros.

Respuesta

13

La "ruta de acceso rápida" que se muestra en la vista de resumen es la ruta de llamada más cara en función del número de muestras incluidas (muestras de la función y muestras de funciones llamadas por la función) y muestras exclusivas (muestras función). Una "muestra" es simplemente el hecho de que la función estaba en la parte superior de la pila cuando el controlador del perfilador capturó la pila (esto ocurre en intervalos de tiempo muy pequeños). Por lo tanto, cuantas más muestras tiene una función, más se está ejecutando.

De forma predeterminada para el análisis de muestreo, se habilita una característica llamada "Just My Code" que oculta las funciones en la pila procedentes de módulos no usuarios (mostrará una profundidad de 1 funciones no usuario si es invocada por un función de usuario; en su caso Application.Run). Las funciones provenientes de módulos sin símbolos cargados o de módulos que se sabe que son de Microsoft quedarían excluidos. Su "Ruta de acceso rápida" en la vista de resumen indica que la pila más cara no tenía nada de lo que el generador de perfiles considera que es su código (que no sea Main). El ejemplo de MSDN muestra más funciones porque las funciones PeopleTrax.* y PeopleNS.* provienen del "código de usuario". "Just My Code" se puede desactivar haciendo clic en el enlace "Mostrar todo el código" en la vista de resumen, pero no recomendaría hacerlo aquí.

Eche un vistazo a las "Funciones que realizan el trabajo más individual" en la vista de resumen. Esto muestra las funciones que tienen los recuentos de muestra exclusivos más altos y, por lo tanto, en función del escenario de creación de perfiles, son las funciones más caras para llamar. Debería ver más de sus funciones (o funciones llamadas por sus funciones) aquí. Además, la vista "Funciones" y "Árbol de llamadas" puede mostrarle más detalles (hay un menú desplegable en la parte superior del informe para seleccionar la vista actual).

En cuanto a las advertencias de símbolos, la mayoría de ellas se esperan porque son módulos de Microsoft (sin incluir System.Data.SQLite.dll).Si bien no necesita los símbolos para estos módulos para analizar su informe correctamente, si marcó "Servidores de símbolos de Microsoft" en "Herramientas -> Opciones -> Depuración -> Símbolos" y volvió a abrir el informe, los símbolos de estos módulos deberían cargarse. . Tenga en cuenta que llevará mucho más tiempo abrir el informe la primera vez porque los símbolos deben descargarse y almacenarse en caché.

La otra advertencia sobre la falla al serializar símbolos en el archivo de informe es el resultado de que el archivo no se puede escribir porque está abierto por otra cosa que impide la escritura. La serialización de símbolos es una optimización que permite al generador de perfiles cargar información de símbolos directamente desde el archivo de informe en el siguiente análisis. Sin serialización de símbolos, el análisis simplemente necesita realizar la misma cantidad de trabajo que cuando se abrió el informe por primera vez.

Y, por último, es posible que también desee probar instrumentación en lugar de muestrear en la configuración de la sesión de creación de perfiles. La instrumentación modifica los módulos que especifique para capturar datos en cada llamada a función (tenga en cuenta que esto puede dar como resultado un archivo .vsp mucho más grande). La instrumentación es ideal para enfocarse en la temporización de piezas específicas de código, mientras que el muestreo es ideal para la recopilación de datos de generación de perfiles con poca carga general.

+0

Instrumentación parece ser más hacia lo que necesito, puedo ver exactamente cuánto tiempo pasó dentro de cada función. ¡Gracias de nuevo! –

+0

@Peter Huene: un poco fuera del tema, pero tengo curiosidad por saber si es posible obtener información de cobertura del código fuente para el código nativo y .net en una sola ejecución. Mi principal ejecutor es un .exe nativo que usa .net dlls – Chubsdad

+0

@Chubsdad: Lo es. Si usa VS 2010 o una versión anterior, debe instrumentar cada ejecutable, tanto nativo como administrado mediante VSInstr y recopilar mediante VSPerfMon. En 2012, la herramienta de cobertura de código (CodeCoverage.exe) instrumentará tanto ejecutables nativos como administrados sobre la marcha (en memoria), siempre que sus archivos .pdbs estén presentes en el momento de la recolección. –

6

¿Te importa demasiado si hablo un poco acerca de los perfiles, qué funciona y qué no?

Compongamos un programa artificial, algunas de cuyas declaraciones están haciendo un trabajo que puede optimizarse, es decir, no son realmente necesarias. Son "cuellos de botella".

La subrutina foo ejecuta un ciclo de CPU que demora un segundo. Supongamos también que las instrucciones CALL y RETURN de la subrutina toman un tiempo insignificante o cero, en comparación con todo lo demás.

Subrutina bar llamadas foo 10 veces, pero 9 de esas veces son innecesarias, que no sabe con anticipación y no puede decir hasta que su atención se dirige hacia allí.

subrutinas A, B, C, ..., son J 10 subrutinas, y que cada llamada bar vez.

La rutina de nivel superior main llama cada una de A a J una vez.

Así el árbol total de la llamada tiene el siguiente aspecto:

main 
    A 
    bar 
     foo 
     foo 
     ... total 10 times for 10 seconds 
    B 
    bar 
     foo 
     foo 
     ... 
    ... 
    J 
    ... 
(finished) 

¿Cuánto tiempo se tome todo? 100 segundos, obviamente.

Ahora veamos las estrategias de creación de perfiles. Las muestras de apilamiento (como, por ejemplo, 1000 muestras) se toman a intervalos uniformes.

  1. ¿Hay algún tiempo para usted? Sí. foo toma el 100% del tiempo de autoaprendizaje. Es un verdadero "punto caliente". ¿Eso te ayuda a encontrar el cuello de botella? No. Porque no está en foo.

  2. ¿Cuál es el camino caliente?Así, las muestras de pila aspecto:

    principal -> A -> Bar -> foo (100 muestras, o el 10%)
    principal -> B -> Bar -> foo (100 muestras, o el 10%)
    ...
    principal -> J -> bar -> foo (100 muestras, o el 10%)

Hay 10 caminos calientes, y ninguno de ellos se ven lo suficientemente grande como para tener que mucho acelerar.

SI SUCEDE A ADIVINAR, y SI EL PERFILADOR LO PERMITE, puede hacer que bar sea la "raíz" de su árbol de llamadas. De allí tendría que ver esto:

bar -> foo (1000 samples, or 100%) 

entonces sabría que foo y bar eran cada uno independientemente responsable del 100% de las veces y por lo tanto son lugares en busca de la optimización. Miras foo, pero por supuesto sabes que el problema no está allí. Luego mira bar y ve las 10 llamadas al foo, y ve que 9 de ellas son innecesarias. Problema resuelto.

SI no sucedió de adivinar, y en su lugar el perfilador simplemente le mostraron el porcentaje de muestras que contienen cada rutina, se podría ver esto:

main 100% 
bar 100% 
foo 100% 
A 10% 
B 10% 
... 
J 10% 

que le indica a la vista main, bar, y foo. Usted ve que main y foo son inocentes. Miras dónde bar llama al foo y ves el problema, así que está resuelto.

Es aún más claro si, además de mostrarle las funciones, se le pueden mostrar las líneas donde se llaman las funciones. De esta forma, puede encontrar el problema sin importar cuán grandes sean las funciones en términos de texto fuente.

AHORA, cambiemos foo para que no entre en la CPU sleep(oneSecond). ¿Cómo cambia eso las cosas?

Lo que significa es que aún tarda 100 segundos en el reloj de pared, pero el tiempo de CPU es cero. El muestreo en una muestra solo de CPU mostrará nada.

Ahora se le indica que pruebe la instrumentación en lugar de muestrear. Incluido entre todas las cosas que te dice, también te dice los porcentajes que se muestran arriba, por lo que en este caso podrías encontrar el problema, asumiendo que bar no era muy grande. (Puede haber razones para escribir pequeñas funciones, pero ¿debería ser uno de ellos el que satisface el generador de perfiles?)

En realidad, el problema principal con la muestra fue que no puede muestrear durante sleep (o E/S u otra bloqueo), y no muestra porcentajes de línea de código, solo porcentajes de función.

Por cierto, 1000 muestras le dan agradables porcentajes de aspecto preciso. Supongamos que tomas menos muestras. ¿Cuántos necesitas para encontrar el cuello de botella? Bueno, dado que el cuello de botella está en la pila el 90% del tiempo, si solo tomaste 10 muestras, sería en aproximadamente 9 de ellas, por lo que aún lo verías. Si incluso tomó tan solo 3 muestras, la probabilidad de que aparezca en dos o más de ellas es del 97.2%.**

Las frecuencias de muestreo altas están demasiado sobrevaloradas, cuando su objetivo es encontrar cuellos de botella.

De todos modos, es por eso que confío en random-pausing.

** ¿Cómo obtuve el 97.2 por ciento? Piense que es como tirar una moneda 3 veces, una moneda muy injusta, donde "1" significa ver el cuello de botella. Hay 8 posibilidades:

 #1s probabality 
0 0 0 0 0.1^3 * 0.9^0 = 0.001 
0 0 1 1 0.1^2 * 0.9^1 = 0.009 
0 1 0 1 0.1^2 * 0.9^1 = 0.009 
0 1 1 2 0.1^1 * 0.9^2 = 0.081 
1 0 0 1 0.1^2 * 0.9^1 = 0.009 
1 0 1 2 0.1^1 * 0.9^2 = 0.081 
1 1 0 2 0.1^1 * 0.9^2 = 0.081 
1 1 1 3 0.1^0 * 0.9^3 = 0.729 

por lo que la probabilidad de ver lo tienen 2 o 3 veces es .081 * 3 + .729 = .972

+0

¡Gran información, gracias! :) –

Cuestiones relacionadas