2010-03-19 9 views
13

Tengo una aplicación Spring que creo que tiene algunos cuellos de botella, por lo que me gustaría ejecutarla con un generador de perfiles para medir qué funciones toman cuánto tiempo. ¿Alguna recomendación de cómo debería hacer eso?Creación de perfiles de una aplicación Java Spring

estoy STS funcionamiento, el proyecto es un proyecto Maven, y yo estoy corriendo primavera 3.0.1

+0

La aplicación de perfiles de Spring no es realmente diferente de la creación de perfiles de cualquier otra aplicación de Java. Es posible que desee ampliar la pregunta para obtener una selección más amplia de respuestas. – skaffman

Respuesta

15

He hecho esto usando Spring AOP.

En algún momento necesito información sobre cuánto tiempo lleva ejecutar algunos métodos en mi proyecto (método del controlador en el ejemplo).

En xml servlet puse

<aop:aspectj-autoproxy/> 

Además, tengo que crear la clase de aspectos:

@Component 
@Aspect 
public class SystemArchitecture { 

    @Pointcut("execution(* org.mywebapp.controller..*.*(..))") 
    public void businessController() { 
    } 
} 

y de perfiles de aspecto:

@Component 
@Aspect 
public class TimeExecutionProfiler { 

    private static final Logger logger = LoggerFactory.getLogger(TimeExecutionProfiler.class); 

    @Around("org.mywebapp.util.aspects.SystemArchitecture.businessController()") 
    public Object profile(ProceedingJoinPoint pjp) throws Throwable { 
     long start = System.currentTimeMillis(); 
     logger.info("ServicesProfiler.profile(): Going to call the method: {}", pjp.getSignature().getName()); 
     Object output = pjp.proceed(); 
     logger.info("ServicesProfiler.profile(): Method execution completed."); 
     long elapsedTime = System.currentTimeMillis() - start; 
     logger.info("ServicesProfiler.profile(): Method execution time: " + elapsedTime + " milliseconds."); 

     return output; 
    } 

    @After("org.mywebapp.util.aspects.SystemArchitecture.businessController()") 
    public void profileMemory() { 
     logger.info("JVM memory in use = {}", (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())); 
    } 
} 

eso es todo. Cuando solicito una página de mi aplicación web, la información sobre el tiempo de ejecución del método y el uso de la memoria JVM se imprime en el archivo de registro de mi webapp.

+0

Hehe, esta es la misma solución que he usado hasta ahora. :-) No es exactamente un generador de perfiles, pero te lleva un largo camino :-) – niklassaers

+0

Hablando de eso, por alguna razón, esto funciona bien en mis métodos de negocios, pero no en mis controladores. ¿Alguna idea de por qué esto podría ser? – niklassaers

+0

Disculpe, no dijo esto en su pregunta :) Si su pregunta es acerca de la aplicación web y si utiliza el contenedor de servlet tomcat, puede usar el servidor SpringSource tc con spring-insight –

2

Se puede usar un perfilador de Java de código abierto como Profiler4J:

http://profiler4j.sourceforge.net/

o Netbeans viene con un generador de perfiles integrado y Eclipse también tiene capacidades de creación de perfiles, sin embargo, encontré que Profiler4J es más fácil de usar ya que tiene un bonito gráfico que le muestra los métodos que consumen más tiempo.

Esto funciona bien en STS (eclipse), simplemente siga las instrucciones en el sitio.

+0

Gracias por el consejo. Parece que la última versión beta de Profiler4J se publicó en 2006, ¿sigue siendo este un proyecto activo? – niklassaers

+0

Parece que todavía no se ha desarrollado activamente, pero cuando lo usé hace unos meses, funcionó bien. Supongo que no se implementará con su proyecto, de modo que si funciona como una herramienta única, no necesita preocuparse. Hay muchos otros que están disponibles comercialmente, de lo contrario, solo use el que viene con eclipse. –

+0

Hmm, lo probé, pero resulta que ni el Call Graph ni el Call Tree están ocupados aunque he instrumentado todas mis clases y las clases de proxy. La memoria y los hilos funcionan bien, aunque – niklassaers

1

Me gustó JRat, aunque como profiler4j no parece estar desarrollado activamente. En cualquier caso, fue simple de usar.

+0

Parece realmente simple de usar, pero cuando lo probé, obtuve errores de Nullpointer del aspecto que teje. No tengo idea de por qué, cuando desactivé JRat, se marcharon. Aunque no me sorprendería si fueran mis errores, pero no sé qué los provocó ni de dónde vinieron. : -I – niklassaers

3

Recomiendo VisualVM para el perfil general de la aplicación. Está disponible en el JDK de la versión 1.6_10, y es mucho más rápido y utilizable que Eclipse TPTP.

Si su aplicación Spring funciona en un servidor de aplicaciones (por ejemplo, Tomcat) puede intentar implementarla en la edición de desarrollador de tc Server (disponible en el STS downloads). Tiene capacidades de monitoreo interesantes.

+0

Gracias por la sugerencia. Estoy trabajando en OS X y, por alguna razón, TPTP no parece existir allí. Me olvidé de tcServer, así que me aseguraré de darle un giro :-) – niklassaers

+0

URL de VisualVm actualizada: https://visualvm.java.net/ – Daimon

+0

@Daimon, gracias por la actualización de la URL, la he actualizado en la respuesta también –

0

Aquí está un general discussion con las herramientas recomendadas & técnicas.

Básicamente, es completamente natural suponer que si quieres saber cómo hacer una aplicación más rápido, debes comenzar por medir cuánto tiempo tardan las funciones. Eso es un enfoque de arriba hacia abajo.

Hay un enfoque ascendente que cuando lo piensas es igual de natural. Eso no es para preguntar sobre el tiempo, sino para preguntar qué está haciendo, predominantemente, y por qué lo está haciendo.

2

Desarrollamos un JMX & Spring AOP basado en la anotación Profil que realiza la supervisión de la producción (invocaciones activas, recuento de invocaciones, tiempo empleado durante las invocaciones, recuento de excepciones, etc.).Las métricas se exponen a través de JMX y pueden recopilarse a través de Visual VM/JConsole y mediante sistemas de supervisión; desarrollamos un complemento Hyperic HQ.

Esta anotación @profiled está empaquetada con muchos otros extras JMX para facilitar el monitoreo de componentes comunes (dbcp, util.concurrent, cxf, jms, etc.) y propuestos bajo una Licencia de software amigable para empresas en http://code.google.com/p/xebia-france/wiki/XebiaManagementExtras.

Espero que esto ayude,

Cyrille (Xebia)

0

Una versión modificada poco de la respuesta de Yuri en la parte superior (la respuesta seleccionada) que calcula los totales de automóviles de duraciones y las organiza desc. Los totales se imprimen al final solamente. Podría ahorrarle 10 mns.

@Component 
    @Aspect 
    public class SystemArchitecture 
    { 

     @Pointcut("execution(* erp..*.*(..))") 
     public void businessController() 
     { 
     } 

     @Pointcut("execution(* TestMain..*.*(..))") 
     public void theEnd() 
     { 
     } 
    } 



    @Component 
    @Aspect 
    public class TimeExecutionProfiler 
    { 

     static Hashtable<String, Long> ht = new Hashtable<String, Long>(); 

     @Around("profiler.SystemArchitecture.businessController()") 
     public Object profile(ProceedingJoinPoint pjp) throws Throwable 
     { 
      long start = System.nanoTime(); 
      Object output = pjp.proceed(); 
      long elapsedTime = System.nanoTime() - start; 
      String methodName = pjp.getSignature().toString(); 
      if (ht.get(methodName) == null) 
      { 
       ht.put(methodName, elapsedTime); 
      } 
      else 
      { 
       ht.put(methodName, ht.get(methodName) + elapsedTime); 
      } 
      // System.out.println(methodName + " : " + elapsedTime + " milliseconds."); 

      return output; 
     } 

     @After("profiler.SystemArchitecture.theEnd()") 
     public void profileMemory() 
     { 
      List<Object> keys = Arrays.asList(ht.keySet().toArray()); 
      java.util.Collections.sort(keys, new Comparator<Object>() 
      { 

       @Override 
       public int compare(Object arg0, Object arg1) 
       { 
        return ht.get(arg1).compareTo(ht.get(arg0)); 
       } 
      }); 

      System.out.println("totals Used:"); 
      for (Object name : keys) 
      { 
       System.out.println("--" + name + " : " + (ht.get(name)/1000000)); 
      } 
      System.out.println("JVM memory in use = " + (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory())); 
     } 
    } 
Cuestiones relacionadas