【问题标题】:Profiling a Java Spring application [closed]分析 Java Spring 应用程序 [关闭]
【发布时间】:2011-01-29 08:39:46
【问题描述】:

我有一个 Spring 应用程序,我认为它存在一些瓶颈,因此我想使用分析器来运行它以测量哪些功能需要多少时间。对我应该如何做有什么建议吗?

我正在运行 STS,该项目是一个 maven 项目,我正在运行 Spring 3.0.1

【问题讨论】:

  • 分析 Spring 应用程序与分析任何其他 java 应用程序并没有什么不同。您可能希望扩大问题范围,以获得更广泛的答案选择。

标签: java spring profiling


【解决方案1】:

您始终可以使用与 Java 捆绑在一起的 Java Mission Controls Flight Recorder 来分析您的代码执行情况

【讨论】:

    【解决方案2】:

    我推荐VisualVM 用于一般应用程序分析。它在 JDK 1.6_10 版本中可用,并且比 Eclipse TPTP 更快且可用。

    如果您的 Spring 应用程序在应用程序服务器(例如 Tomcat)中工作,您可以尝试将其部署到 tc Server 开发人员版本(在 STS downloads 中提供)。它具有有趣的监控功能。 tc Server 开发者版好像没有维护了。)

    UPDATE 2019.02.22.:更新了 VisualVM url(感谢 @Jeff)和 tc 服务器信息。我个人目前使用Glowroot 来监控在应用服务器中运行的Spring 应用程序。

    【讨论】:

    • 感谢您的建议。我正在使用 OS X,由于某种原因,TPTP 似乎不存在。我忘记了 tcServer,所以我一定会试一试 :-)
    • @Daimon,感谢 URL 更新,我也在答案中更新了它
    【解决方案3】:

    顶部的 Yuri 答案(所选答案)的稍微修改版本,它会自动计算持续时间的总数并按顺序排列。总数仅在最后打印。 可能会为您节省 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()));
            }
        }
    

    【讨论】:

      【解决方案4】:

      我们开发了一个基于 JMX 和 Spring AOP 的 @Profiled 注释,它进行生产监控(活动调用、调用计数、调用期间花费的时间、异常计数等)。指标通过 JMX 公开,可以通过 Visual VM/JConsole 和监控系统收集;我们开发了一个 Hyperic HQ 插件。

      此@profiled 注释与许多其他 JMX 附加组件打包在一起,以简化对常见组件(dbcp、util.concurrent、cxf、jms 等)的监控,并在 http://code.google.com/p/xebia-france/wiki/XebiaManagementExtras 的商业友好 Apache 软件许可下提出。

      希望这会有所帮助,

      西里尔 (Xebia)

      【讨论】:

        【解决方案5】:

        这是一个general discussion,其中包含推荐的工具和技术。

        基本上,如果您想了解如何让应用程序变得更快,您会很自然地假设您应该从测量函数需要多长时间开始。 这是一种自上而下的方法。

        有一种自下而上的方法,当您考虑它时,它同样自然。这不是询问时间,而是询问它主要在做什么,以及为什么这样做。

        【讨论】:

          【解决方案6】:

          我喜欢JRat,尽管它和 profiler4j 一样似乎没有被积极开发。无论如何,它使用起来很简单。

          【讨论】:

          • 看起来使用起来很简单,但是当我尝试它时,我从切面编织中得到了Nullpointer错误。不知道为什么,当我禁用 JRat 时,它们就消失了。虽然如果它们是我的错误我不会感到惊讶,但我不知道是什么触发了它们或它们来自哪里。 :-我
          【解决方案7】:

          我已经使用 Spring AOP 完成了这项工作。

          有时我需要有关在我的项目中执行某些方法(例如控制器的方法)需要多少时间的信息。

          在 servlet 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 的日志文件中。

          【讨论】:

          • 呵呵,这实际上是我迄今为止使用的相同解决方法。 :-) 不是一个分析器,但可以让你走很长一段路:-)
          • 说到,出于某种原因,这在我的业务方法上运行良好,但不适用于我的控制器。知道为什么会这样吗?
          • 对不起,你没有在你的问题中这么说 :) 如果你的问题是关于 web 应用程序并且如果你使用 tomcat servlet 容器,你可以使用 SpringSource tc server with spring-insight
          • 第二条评论:您的 applicationContext.xml 是否包含
          • 嗨,对不起,我没有在我的问题中说这个,我认为你的答案很重要。 :-) 我在 applicationContext.xml 中确实有一个组件扫描,但是当我将此方面添加到控制器时,控制器就不再显示了。也许我把它们弄错了
          【解决方案8】:

          您可以使用开源的 java profiler,例如 Profiler4J:

          http://profiler4j.sourceforge.net/

          或者 Netbeans 带有内置的分析器,而 Eclipse 也具有分析功能,但是我发现 Profiler4J 更易于使用,因为它有一个漂亮的图表,可以向您展示最耗时的方法。

          这在 STS (eclipse) 中运行良好,只需按照网站上的说明进行操作即可。

          【讨论】:

          • 感谢您的提示。 Profiler4J 的最后一个测试版似乎是在 2006 年发布的,这仍然是一个活跃的项目吗?
          • 看起来它可能还没有被积极开发,但是当我几个月前使用它时,它运行良好。我想它不会与您的项目一起部署,所以如果它作为一次性工具工作,您无需担心。市面上还有很多其他的,否则就用eclipse自带的吧。
          • 嗯,我试过了,但事实证明,即使我已经检测了所有类和代理类,调用图和调用树都没有填充。不过,内存和线程运行良好
          • 你按下小快照按钮了吗?那应该填充图表。在 Web 应用程序中,您可以使用工具栏上的按钮清除寄存器,执行要分析的操作,然后单击快照按钮以填充该操作的图表。
          猜你喜欢
          • 2010-12-07
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-04-23
          • 1970-01-01
          • 1970-01-01
          • 2011-11-26
          • 1970-01-01
          相关资源
          最近更新 更多