Профилирование приложения Java Spring

У меня есть приложение Spring, которое, как я считаю, имеет некоторые узкие места, поэтому я хотел бы запустить его с профилировщиком, чтобы определить, какие функции занимают сколько времени. Любые рекомендации, как я должен это делать?

Я запускаю STS, проект - проект maven, и я запускаю Spring 3.0.1

Ответы

Ответ 1

Я сделал это с помощью Spring AOP.

Иногда мне нужна информация о том, сколько времени требуется для выполнения некоторых методов в моем проекте (пример контроллера).

В сервлет xml я положил

<aop:aspectj-autoproxy/>

Кроме того, мне нужно создать класс для аспектов:

@Component
@Aspect
public class SystemArchitecture {

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

И аспект профилирования:

@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()));
    }
}

Это все. Когда я запрашиваю страницу из моего webapp, информация о времени выполнения метода и использовании памяти JVM выводится в моем файле журнала webapp.

Ответ 2

Я рекомендую VisualVM для общего профилирования приложений. Он доступен в JDK версии 1.6_10, а imho - намного быстрее и удобнее, чем Eclipse TPTP.

Если ваше приложение Spring работает на сервере приложений (например, Tomcat), вы можете попытаться развернуть его в редакторе разработчиков tc Server (доступно в Загрузка STS). Он имеет интересные возможности мониторинга.

Ответ 3

Вы можете использовать профилировщик java с открытым исходным кодом, например Profiler4J:

http://profiler4j.sourceforge.net/

или Netbeans поставляется со встроенным профилировщиком, и Eclipse также имеет возможности профилирования, однако я нашел, что Profiler4J проще в использовании, поскольку у него есть хороший график, показывающий вам наиболее трудоемкие методы.

Это хорошо работает в STS (eclipse), просто следуйте инструкциям на сайте.

Ответ 4

Мы разработали JMX и Spring AOP, основанную на @Profiled аннотации, которая осуществляет мониторинг производства (активные вызовы, подсчет вызовов, время, затраченное на вызовы, количество исключений и т.д.). Показатели отображаются через JMX и могут быть собраны через Visual VM/JConsole и системами мониторинга; мы разработали плагин Hyperic HQ.

Эта аннотация @profiled упакована со многими другими дополнительными функциями JMX для облегчения мониторинга общих компонентов (dbcp, util.concurrent, cxf, jms и т.д.) и предлагается в соответствии с бизнес-совместимой лицензией на программное обеспечение Apache по адресу http://code.google.com/p/xebia-france/wiki/XebiaManagementExtras.

Надеюсь, что это поможет,

Кирилл (Xebia)

Ответ 5

Мне понравился JRat, хотя, как и у profiler4j, он, похоже, не активно развивается. В любом случае это было простое использование.

Ответ 6

Здесь общая дискуссия с рекомендуемыми инструментами и методами.

В принципе, вполне естественно предположить, хотите ли вы быстрее узнать, как сделать приложение, и начать с него, измеряя, как долго выполняются функции. Это подход сверху вниз.

Там подход снизу вверх, когда вы думаете об этом, так же естественно. Это не вопрос о времени, а вопрос о том, что он делает, в основном, и почему он это делает.

Ответ 7

Немного измененная версия ответа Yuri сверху (выбранный ответ), который автоматически вычисляет итоговые значения продолжительности и упорядочивает их desc. Итоговые данные печатаются только в конце. Мог бы спасти вас 10 мн.

    @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()));
        }
    }