Java GC Log Time解析

简介: 通常,我们在了解应用服务的性能时,都会去在所定义的垃圾收集日志文件中去分析GC活动轨迹,在gc.log文件中,我们经常会看到每个GC事件所打印的三种时间类型: “ User ”、“ Sys ”及“ Real ”,它们分别表示什么呢?具有哪些象征性意义呢?本文将结合作者的相关实际经验进行简要解析,希望阅读完本篇文章后对大家在GC Log这块的问题定位与分析有所帮助。

      通常,我们在了解应用服务的性能时,都会去在所定义的垃圾收集日志文件中去分析GC活动轨迹,在gc.log文件中,我们经常会看到每个GC事件所打印的三种时间类型:

      “ User ”、“ Sys ”及“ Real ”,它们分别表示什么呢?具有哪些象征性意义呢?本文将结合作者的相关实际经验进行简要解析,希望阅读完本篇文章后对大家在GC Log这块的问题定位与分析有所帮助。

      以下为基于G 1垃圾回收策略的GC Log内容,因篇幅有限,仅显示局部内容:


[administrator@JavaLangOutOfMemory luga %]less echo-admin-gc.log
... ...
2015-09-14T12:32:24.398-0700: 0.356: [GC pause (G1 Evacuation Pause) (young), 0.0215287 secs]
   [Parallel Time: 20.0 ms, GC Workers: 8]
      [GC Worker Start (ms): Min: 355.9, Avg: 356.3, Max: 358.4, Diff: 2.4]
      [Ext Root Scanning (ms): Min: 0.0, Avg: 6.4, Max: 16.7, Diff: 16.7, Sum: 51.4]
      [Update RS (ms): Min: 0.0, Avg: 1.0, Max: 2.5, Diff: 2.5, Sum: 8.2]
         [Processed Buffers: Min: 0, Avg: 1.1, Max: 5, Diff: 5, Sum: 9]
      [Scan RS (ms): Min: 0.0, Avg: 0.0, Max: 0.0, Diff: 0.0, Sum: 0.0]
      [Code Root Scanning (ms): Min: 0.0, Avg: 0.0, Max: 0.1, Diff: 0.1, Sum: 0.1]
      [Object Copy (ms): Min: 2.9, Avg: 11.9, Max: 17.5, Diff: 14.6, Sum: 95.3]
      [Termination (ms): Min: 0.0, Avg: 0.1, Max: 0.2, Diff: 0.2, Sum: 0.9]
         [Termination Attempts: Min: 1, Avg: 2.5, Max: 5, Diff: 4, Sum: 20]
      [GC Worker Other (ms): Min: 0.0, Avg: 0.1, Max: 0.1, Diff: 0.1, Sum: 0.5]
      [GC Worker Total (ms): Min: 17.5, Avg: 19.6, Max: 19.9, Diff: 2.4, Sum: 156.5]
      [GC Worker End (ms): Min: 375.8, Avg: 375.9, Max: 375.9, Diff: 0.1]
   [Code Root Fixup: 0.0 ms]
   [Code Root Purge: 0.0 ms]
   [Clear CT: 0.5 ms]
   [Other: 1.0 ms]
      [Choose CSet: 0.0 ms]
      [Ref Proc: 0.4 ms]
      [Ref Enq: 0.0 ms]
      [Redirty Cards: 0.4 ms]
      [Humongous Register: 0.0 ms]
      [Humongous Reclaim: 0.0 ms]
      [Free CSet: 0.0 ms]
   [Eden: 12.0M(12.0M)->0.0B(14.0M) Survivors: 0.0B->2048.0K Heap: 12.6M(252.0M)->7848.3K(252.0M)]
 [Times: user=0.08 sys=0.00, real=0.02 secs] 
2015-09-14T12:32:24.932-0700: 0.889: [GC pause (G1 Evacuation Pause) (young), 0.0469650 secs]

      从上述的输出文件中,我们可以看到在年轻代GC 事件后面有3种不同时间的详细打印:

[Times: user=0.08 sys=0.00, real=0.02 secs] 。如何在应用程序运行过程中输出GC Log?可参考之前的文章:Java虚拟机三件套解析

      当拿到这份GC 日志文件,我们会遇到很多很多问题:每个单个GC事件花费的时间都会在GC日志中报告。在每个GC事件中,都有“用户”,“ 系统”和“实时”。这些时间是代表什么意思?它们之间究竟有什么本质区别?我们如何去打印,什么时间去监控?

      在我们了解GC Time之前,我们花几分钟时间来了解Linux / Unix命令的“时间”。具体如下操作:


[administrator@JavaLangOutOfMemory ~ %] time ls
Desktop      Movies      activemq    gateway      luga
Documents    Music      cpu      go      monitoring-micrometer
Downloads    Pictures    curl-format.txt    goPro      nacos-docker
IdeaProjects    Public      deploy-demo.yaml  java      openshift
Library      SpringCloud2.x    docker      k8s
real     0m0.003s
user     0m0.000s
sys      0m0.001s

       通过time ls命令,我们看到这样的输出:

       “ time ls” 命令首先显示“ ls”命令的执行输出,其中列出了当前目录中的所有目录/文件:

接下来,我们看到执行“ ls”所花费的时间,即:“真实”,“用户”,“ 系统” 时间。这是我们在GC日志中看到的相同数据。

       下面是在每种情况下StackOverflow中提供的一个很好的定义:

       Real(实际时间)是挂钟时间-从事件开始到结束的时间。这是所有经过的时间,包括其他进程使用的时间片以及该进程花费的时间被阻塞(例如,如果它正在等待I / O完成)。

       User(用户时间)是进程中用户模式代码(内核外部)所花费的CPU时间片。这只是执行过程中使用的实际CPU时间。该进程花费的其他进程和时间不计入该数字。

       Sys(系统时间)是进程中在内核中花费的CPU时间量。这意味着在内核内部执行系统调用所花费的CPU时间,而不是库代码仍在用户空间中运行。就像“用户”一样,这只是进程使用的CPU时间。

       User + Sys将告诉我们:我们的进程使用了多少实际CPU时间。请注意,这涉及所有CPU,因此,如果该进程具有多个线程,则有可能超过Real Times的挂钟时间。

       刚才我们讲到了Linux/Unix时间概念,现在我们着重看下Java GC Times。这与GC日志记录中应用的概念相同。

      在Java GC Times概念中,每个单个GC事件花费的时间都会在GC日志中报告。在每个GC事件中,都有“user”,“ sys”和“real”。这些时间是什么意思?它们之间有什么区别?

       Real(实际时间)指GC事件的总经过时间。这基本上是您在时钟中看到的时间。

       User(用户时间)指用户模式代码(内核外部)所花费的CPU时间。

       Sys(系统时间)指内核中花费的CPU时间。这意味着在内核内部执行系统调用所花费的CPU时间,而不是库代码仍在用户空间中运行。

       让我们看几个简单示例,以便更好地理解这个概念。

示例1:

[Times: user=12.93 sys=2.01, real=1.03 secs]

      在此示例中:“user” +“sys”远大于“real”。这是因为此日志时间是从JVM收集的,在JVM中,多核/多处理器服务器上配置了多个GC线程。当多个线程并行执行GC时,工作负载将在这些线程之间共享。因此,实际时钟时间(“real”)比CPU总时间(“user” +“ sys”)少得多。

示例2:

[Times: user=0.12 sys=0.00, real=0.12 secs]

      上面是从串行垃圾收集器收集的GC时间的示例。由于串行垃圾收集器始终仅使用单个线程,因此实时等于用户和系统时间的总和。

      在实际的业务场景中,考虑性能优化时,我们主要偏向在为客户优化响应时间。客户不在乎我们使用多少GC线程或拥有多少处理器。因此,我们需要重点关注“real”时间,但这并不意味着“ sys”或“ user”时间并不重要。它们对于查看是否要增加GC线程数或CPU处理器数以减少GC暂停时间也很重要。

      在正常的(所有)GC事件中,Real Time将小于(User+Sys)Time。这是因为多个GC线程同时工作以分担工作量,因此实时时间将少于用户+系统时间。假设(User+Sys)Time为2秒。如果5个GC线程同时工作,则实时应该在400毫秒左右(2秒/ 5个GC线程)附近。但是在某些情况下,我们可能会看到Real Time >(User+Sys)Time

       我们看一下示例:


[Times: user=0.80 sys=0.05, real=20.37 secs]

      如果我们在GC日志中发现多次出现此情况(Real Time明显大于User Time与Sys Time之和),则可能表明存在以下问题之一:

       1、I / O繁忙

       2、CPU不足

      下面我们针对出现的性能问题进行分析:

I / O繁忙

      当服务器上发生大量I / O活动(即网络/磁盘访问/用户交互)时,实时性往往会在很大程度上飙升。作为GC日志记录的一部分,我们的应用程序进行磁盘访问。如果服务器上的I / O活动繁重,则GC事件可能会搁浅,从而导致实时峰值。

      注意:即使我们的应用程序没有引起繁重的I / O活动,服务器上的其他进程也可能导致繁重的I / O活动,从而导致较高的实时性。

      我们可以在Linux/Unix中使用sar(系统活动报告)监视服务器上的I / O活动。具体为:


[administrator@JavaLangOutOfMemory ~ %]sar -d -p 1

      上面的命令每1秒报告一次对设备的读取/秒和写入/秒。有关“ sar”命令的更多详细信息,请参官网教程。

       如果我们发现服务器上的I / O活动很高,则可以执行以下任一操作来解决此问题:

       1、如果我们的应用程序引起了较高的I / O活动,请优化应用程序的I / O活动。

       2、消除导致服务器上大量I / O活动的进程

       3、将我们的应用程序移到I / O活动较少的其他服务器上

CPU不足

      如果我们的服务器上正在运行多个进程,并且我们的应用程序没有足够的CPU周期来运行,它将开始等待。当应用程序开始等待时,实时将大大高于用户+系统时间。

      我们可以使用“ top”之类的命令或监视工具(nagios,newRelic,AppDynamics…)来观察服务器上的CPU利用率。如果我们发现CPU使用率很高,并且进程没有足够的周期来运行,则可以执行以下一项操作来解决此问题:

       1、减少服务器上正在运行的进程数,以便我们的应用程序有运行的资源空间。

       2、增加CPU容量,将应用服务移至具有更多CPU核心的更大实例类型。

       3、将我们的应用程序移到具有足够CPU容量的新服务器上。

     基于以上的解析过程,希望本文对大家有所帮助,使得我们能够熟悉GC Log里面的奥秘,以便我们的应用程序在运行过程中以获得最佳性能表现。


相关文章
|
11月前
|
机器学习/深度学习 JSON Java
Java调用Python的5种实用方案:从简单到进阶的全场景解析
在机器学习与大数据融合背景下,Java与Python协同开发成为企业常见需求。本文通过真实案例解析5种主流调用方案,涵盖脚本调用到微服务架构,助力开发者根据业务场景选择最优方案,提升开发效率与系统性能。
2269 0
|
11月前
|
Java
Java的CAS机制深度解析
CAS(Compare-And-Swap)是并发编程中的原子操作,用于实现多线程环境下的无锁数据同步。它通过比较内存值与预期值,决定是否更新值,从而避免锁的使用。CAS广泛应用于Java的原子类和并发包中,如AtomicInteger和ConcurrentHashMap,提升了并发性能。尽管CAS具有高性能、无死锁等优点,但也存在ABA问题、循环开销大及仅支持单变量原子操作等缺点。合理使用CAS,结合实际场景选择同步机制,能有效提升程序性能。
|
11月前
|
Java 开发者
Java并发编程:CountDownLatch实战解析
Java并发编程:CountDownLatch实战解析
660 100
|
10月前
|
存储 安全 Java
《数据之美》:Java集合框架全景解析
Java集合框架是数据管理的核心工具,涵盖List、Set、Map等体系,提供丰富接口与实现类,支持高效的数据操作与算法处理。
|
11月前
|
Java 开发者
Java 函数式编程全解析:静态方法引用、实例方法引用、特定类型方法引用与构造器引用实战教程
本文介绍Java 8函数式编程中的四种方法引用:静态、实例、特定类型及构造器引用,通过简洁示例演示其用法,帮助开发者提升代码可读性与简洁性。
|
11月前
|
安全 Java API
Java SE 与 Java EE 区别解析及应用场景对比
在Java编程世界中,Java SE(Java Standard Edition)和Java EE(Java Enterprise Edition)是两个重要的平台版本,它们各自有着独特的定位和应用场景。理解它们之间的差异,对于开发者选择合适的技术栈进行项目开发至关重要。
1632 1
|
10月前
|
存储 人工智能 算法
从零掌握贪心算法Java版:LeetCode 10题实战解析(上)
在算法世界里,有一种思想如同生活中的"见好就收"——每次做出当前看来最优的选择,寄希望于通过局部最优达成全局最优。这种思想就是贪心算法,它以其简洁高效的特点,成为解决最优问题的利器。今天我们就来系统学习贪心算法的核心思想,并通过10道LeetCode经典题目实战演练,带你掌握这种"步步为营"的解题思维。
|
监控 安全 Apache
什么是Apache日志?为什么Apache日志分析很重要?
Apache是全球广泛使用的Web服务器软件,支持超过30%的活跃网站。它通过接收和处理HTTP请求,与后端服务器通信,返回响应并记录日志,确保网页请求的快速准确处理。Apache日志分为访问日志和错误日志,对提升用户体验、保障安全及优化性能至关重要。EventLog Analyzer等工具可有效管理和分析这些日志,增强Web服务的安全性和可靠性。
673 9
|
监控 容灾 算法
阿里云 SLS 多云日志接入最佳实践:链路、成本与高可用性优化
本文探讨了如何高效、经济且可靠地将海外应用与基础设施日志统一采集至阿里云日志服务(SLS),解决全球化业务扩展中的关键挑战。重点介绍了高性能日志采集Agent(iLogtail/LoongCollector)在海外场景的应用,推荐使用LoongCollector以获得更优的稳定性和网络容错能力。同时分析了多种网络接入方案,包括公网直连、全球加速优化、阿里云内网及专线/CEN/VPN接入等,并提供了成本优化策略和多目标发送配置指导,帮助企业构建稳定、低成本、高可用的全球日志系统。
1490 55

热门文章

最新文章

推荐镜像

更多
  • DNS