2010-03-11 11 views

Respuesta

38

La creación de perfiles es un tema que tiene más de una escuela de pensamiento.

El más popular es que se obtiene medidas. Es decir, intenta ver cuánto tiempo tarda cada función y/o cuántas veces se llama. Claramente, si una función lleva muy poco tiempo, acelerarla le hará ganar poco. Pero si lleva mucho tiempo, entonces tiene que hacer un trabajo de detective para descubrir qué parte de la función es responsable del tiempo. No espere que los tiempos de las funciones sumen al tiempo total, porque las funciones se llaman entre sí, y la función de razón A puede tomar mucho tiempo porque llama a la función B que también lleva mucho tiempo.

Este enfoque puede encontrar muchos problemas, pero depende de que sea un buen detective y sea capaz de pensar claramente sobre diferentes tipos de tiempo, como el tiempo de pared frente al tiempo de CPU y el tiempo propio frente al tiempo inclusivo . Por ejemplo, una aplicación puede parecer lenta, pero los tiempos de las funciones pueden informarse casi como cero. Esto puede deberse a que el programa está vinculado a E/S. Si la E/S es algo que esperas, puede estar bien, pero puede estar haciendo algo de E/S que no conoces, y luego vuelves al trabajo detectivesco.

La expectativa general con los perfiladores es que si puedes arreglar lo suficiente para obtener una aceleración del 10% o 20%, eso es bastante bueno, y nunca escuché historias de perfiladores que se usan repetidamente para obtener aceleraciones de mucho más que eso.

Otro enfoque no es medir, pero captura. Se basa en la idea de que, durante un tiempo en el que el programa tarda más (de la hora del reloj de pared) de lo que te gustaría, quieres saber qué está haciendo, predominantemente, y una forma de averiguarlo es detenerlo. y preguntar, o tomar una instantánea de su estado y analizarlo para comprender completamente lo que está haciendo y por qué lo está haciendo en ese momento particular.Si haces esto varias veces y ves algo que intenta hacer varias veces, entonces esa actividad es algo que podrías optimizar fructíferamente. La diferencia es que no está preguntando cuánto; usted está preguntando qué y por qué. Here's another explanation. (Observe que la velocidad de tomar una instantánea así no importa, porque no está preguntando sobre el tiempo, está preguntando qué está haciendo el programa y por qué).

En el caso de Java, here is one low-tech but highly effective manera para hacer eso, o puede usar el botón "pausa" en Eclipse. Otra forma es usar un tipo particular de generador de perfiles, uno que muestree toda la pila de llamadas, en la hora del reloj de pared (no en la CPU a menos que desee cegar a la E/S), cuando desee que muestree (por ejemplo, no cuando se espera la entrada del usuario), y se resume en el nivel de las líneas de código, no solo en el nivel de funciones, y el porcentaje de tiempo, no el tiempo absoluto. Para obtener el porcentaje de tiempo, debe decirle, para cada línea de código que aparece en cualquier muestra, el porcentaje de muestras que contiene esa línea, porque si pudiera hacer desaparecer esa línea, ahorraría ese porcentaje. (Debe ignorar otras cosas de las que intenta hablar, como gráficos de llamadas, recursividad y tiempo de autocomprobación). Hay muy pocos perfiladores que cumplan esta especificación, pero uno es RotateRight/Zoom, pero no estoy seguro si funciona con Java, y puede haber otros.

En algunos casos puede ser difícil obtener muestras de la pila cuando lo desee, durante el tiempo de lentitud real. Entonces, como lo que busca son porcentajes, puede hacer cualquier cosa con el código que hace que sea más fácil obtener muestras sin alterar los porcentajes. Una forma es amplificar el código envolviendo un bucle temporal alrededor de, digamos, 100 iteraciones. Otra forma es, bajo un depurador, establecer un punto de interrupción de cambio de datos. Esto hará que el código se interprete de 10 a 100 veces más lento que lo normal. Otra forma es emplear un temporizador de reloj despertador para que se active durante el período de lentitud y usarlo para tomar una muestra.

Con la técnica de captura, si la usa repetidamente para buscar y realizar optimizaciones múltiples, puede esperar alcanzar un rendimiento casi óptimo. En el caso del software grande, donde los cuellos de botella son más numerosos, esto puede significar factores sustanciales. Las personas en Stack   Overflow informaron factores de 7x a 60x. Here is a detailed example of 43x.

La técnica de captura tiene problemas con los casos en los que es difícil determinar por qué los hilos están esperando cuando están, como cuando se espera que una transacción se complete en otro procesador. (La medición tiene el mismo problema). En esos casos, utilizo un método laborioso para fusionar registros con sello de tiempo.

+0

Tenga en cuenta que no tiene que ser "cualquiera/o" - a menudo es útil * medir * alguna "ejecución de prueba típica" de forma no invasiva, luego utilice un generador de perfiles como herramienta de captura para encontrar zonas activas. Realice sus cambios, usando el perfilador de forma iterativa, y luego vuelva a ejecutar las pruebas de medición. –

+0

@Jon: vuelvo a ejecutar la medición (normalmente solo un cronómetro) para ver cuánto tiempo perdí. Donde soy un fanático es en el método de encontrar qué arreglar, que rara vez es un "punto de acceso" como lo defino (una región donde el contador del programa se cuelga) o un "cuello de botella" (un lugar donde el trabajo necesario se llena arriba). Por lo general, son pequeñas frases (o menos) que terminan invocando montones de código (incluido IO) que nunca hubieras adivinado cuando lo codificaste. –

+0

Descubrí que simplemente usar el botón de pausa en el depurador de IDEA no era suficiente debido a la gran cantidad de subprocesos.Necesitaba encontrar el hilo correcto cada vez, una gran molestia. Pero, encontré la misma información simplemente tirando la pila a intervalos regulares. No es necesario pausar el programa :-) – oligofren

2

JProfiler viene con su manual de ayuda. Encontré eso para ser muy bueno.

4

Como recién llegado a la creación de perfiles debe comenzar simplemente buscando métodos que tengan tiempos de ejecución largos y/o que se invoquen muchas veces durante los patrones de uso típicos/donde ocurren los cuellos de botella.

No estoy seguro de cómo funciona la integración de Eclipse con JProfiler, ya que utilizo principalmente NetBeans. Sin embargo, en NetBeans hay una vista de "instantánea" que muestra una jerarquía de invocaciones de métodos con tiempos de ejecución que suman hasta el 100%. Busco las partes de la jerarquía que ocupan un (relativamente) gran% del tiempo total. A partir de ahí, debe pensar qué están haciendo esos métodos y qué podría estar causando que sean lentos.

Por ejemplo: me di cuenta de que un método al que se llamaba con frecuencia, en general, tomaba demasiado tiempo para completarse y era un serio cuello de botella. Para resumir, resultó que el código estaba verificando para ver si un artículo estaba presente en una colección usando el método .contains(), y la colección era una lista enlazada. La razón por la que esto es un problema es porque las listas vinculadas tienen una complejidad temporal de O (n) para funciones como .contains(). La solución en este caso fue bastante simple, ya que pude reemplazar la Lista Vinculada con un Conjunto Hash, que realiza .contains() mucho más rápido, en O (1) vez.

+0

good insight !! gracias –

1

Puede encontrar el libro Java Platform Performance interesante. Publicado por Sun Microsystems.

9

Estoy utilizando Yourkit Java Profiler 11.0 y es muy bueno para optimizar la memoria y controlar el tiempo de la CPU. También el sitio web de yourkit tiene una buena base de conocimientos y temas de ayuda.

Cuestiones relacionadas