¿Algún tutorial de perfiles de Java recomendado?

¿Hay algún tutorial de perfiles de aplicaciones Java recomendado?

Ahora estoy usando JProfiler y Eclipse Test & Performance Tools Platform (TPTP) con mi perfil. Sin embargo, aunque equipado con armas maravillosas, como alguien nuevo en el perfil de Java, todavía me falta la teoría general y la habilidad para identificar el cuello de botella.

El perfil es un tema que tiene más de una escuela de pensamiento.

El más popular es que procedas obteniendo 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 con claridad sobre diferentes tipos de tiempo, como el tiempo de reloj de pared frente al tiempo de CPU, y el tiempo de tiempo libre 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 progtwig 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 del 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, sino capturar . Se basa en la idea de que, durante un tiempo en el que el progtwig 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ás preguntando cuánto ; estás preguntando qué y por qué . Aquí hay otra explicación. (Tenga en cuenta que la velocidad de tomar una instantánea así no importa, porque no está preguntando sobre el tiempo, está preguntando qué está haciendo el progtwig y por qué).

En el caso de Java, aquí hay una manera de hacerlo de baja tecnología pero muy efectiva , 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 stack 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 que trata de contarle, 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 de si funciona con Java, y puede haber otros.

En algunos casos, puede ser difícil obtener muestras de la stack 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 Desbordamiento de stack informaron factores de 7x a 60x. Aquí hay un ejemplo detallado de 43x.

La técnica de captura tiene problemas con casos en los que es difícil averiguar 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.

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

Como recién llegado al perfil, 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 uso 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 sumn 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: noté que un método que se llamaba frecuentemente en general tomaba demasiado tiempo para completarse, y era un serio cuello de botella. Para abreviar, resultó que el código estaba verificando si un artículo estaba presente en una colección con el método .contains() y la colección era una lista enlazada. La razón por la cual este 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.

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

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