Java GC Log Time解析

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 通常,我们在了解应用服务的性能时,都会去在所定义的垃圾收集日志文件中去分析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里面的奥秘,以便我们的应用程序在运行过程中以获得最佳性能表现。


相关文章
|
8月前
|
机器学习/深度学习 人工智能 Java
Java机器学习实战:基于DJL框架的手写数字识别全解析
在人工智能蓬勃发展的今天,Python凭借丰富的生态库(如TensorFlow、PyTorch)成为AI开发的首选语言。但Java作为企业级应用的基石,其在生产环境部署、性能优化和工程化方面的优势不容忽视。DJL(Deep Java Library)的出现完美填补了Java在深度学习领域的空白,它提供了一套统一的API,允许开发者无缝对接主流深度学习框架,将AI模型高效部署到Java生态中。本文将通过手写数字识别的完整流程,深入解析DJL框架的核心机制与应用实践。
500 3
|
8月前
|
存储 设计模式 Java
重学Java基础篇—ThreadLocal深度解析与最佳实践
ThreadLocal 是一种实现线程隔离的机制,为每个线程创建独立变量副本,适用于数据库连接管理、用户会话信息存储等场景。
288 5
|
8月前
|
存储 监控 安全
重学Java基础篇—类的生命周期深度解析
本文全面解析了Java类的生命周期,涵盖加载、验证、准备、解析、初始化、使用及卸载七个关键阶段。通过分阶段执行机制详解(如加载阶段的触发条件与技术实现),结合方法调用机制、内存回收保护等使用阶段特性,以及卸载条件和特殊场景处理,帮助开发者深入理解JVM运作原理。同时,文章探讨了性能优化建议、典型异常处理及新一代JVM特性(如元空间与模块化系统)。总结中强调安全优先、延迟加载与动态扩展的设计思想,并提供开发建议与进阶方向,助力解决性能调优、内存泄漏排查及框架设计等问题。
375 5
|
8月前
|
Java 开发者
重学Java基础篇—Java类加载顺序深度解析
本文全面解析Java类的生命周期与加载顺序,涵盖从加载到卸载的七个阶段,并深入探讨初始化阶段的执行规则。通过单类、继承体系的实例分析,明确静态与实例初始化的顺序。同时,列举六种触发初始化的场景及特殊场景处理(如接口初始化)。提供类加载完整流程图与记忆口诀,助于理解复杂初始化逻辑。此外,针对空指针异常等问题提出排查方案,并给出最佳实践建议,帮助开发者优化程序设计、定位BUG及理解框架机制。最后扩展讲解类加载器层次与双亲委派机制,为深入研究奠定基础。
325 0
|
8月前
|
安全 IDE Java
重学Java基础篇—Java Object类常用方法深度解析
Java中,Object类作为所有类的超类,提供了多个核心方法以支持对象的基本行为。其中,`toString()`用于对象的字符串表示,重写时应包含关键信息;`equals()`与`hashCode()`需成对重写,确保对象等价判断的一致性;`getClass()`用于运行时类型识别;`clone()`实现对象复制,需区分浅拷贝与深拷贝;`wait()/notify()`支持线程协作。此外,`finalize()`已过时,建议使用更安全的资源管理方式。合理运用这些方法,并遵循最佳实践,可提升代码质量与健壮性。
255 1
|
8月前
|
监控 Java 应用服务中间件
Tomcat log日志解析
理解和解析Tomcat日志文件对于诊断和解决Web应用中的问题至关重要。通过分析 `catalina.out`、`localhost.log`、`localhost_access_log.*.txt`、`manager.log`和 `host-manager.log`等日志文件,可以快速定位和解决问题,确保Tomcat服务器的稳定运行。掌握这些日志解析技巧,可以显著提高运维和开发效率。
814 13
|
8月前
|
SQL druid Oracle
【YashanDB知识库】yasdb jdbc驱动集成druid连接池,业务(java)日志中有token IDENTIFIER start异常
客户Java日志中出现异常,影响Druid的merge SQL功能(将SQL字面量替换为绑定变量以统计性能),但不影响正常业务流程。原因是Druid在merge SQL时传入null作为dbType,导致无法解析递归查询中的`start`关键字。
|
8月前
|
传感器 监控 Java
Java代码结构解析:类、方法、主函数(1分钟解剖室)
### Java代码结构简介 掌握Java代码结构如同拥有程序世界的建筑蓝图,类、方法和主函数构成“黄金三角”。类是独立的容器,承载成员变量和方法;方法实现特定功能,参数控制输入环境;主函数是程序入口。常见错误包括类名与文件名不匹配、忘记static修饰符和花括号未闭合。通过实战案例学习电商系统、游戏角色控制和物联网设备监控,理解类的作用、方法类型和主函数任务,避免典型错误,逐步提升编程能力。 **脑图速记法**:类如太空站,方法即舱段;main是发射台,static不能换;文件名对仗,括号要成双;参数是坐标,void不返航。
340 5
|
8月前
|
人工智能 运维 监控
一招高效解析 Access Log,轻松应对泼天流量
一招高效解析 Access Log,轻松应对泼天流量
155 0
一招高效解析 Access Log,轻松应对泼天流量
|
9月前
|
Java API 数据处理
深潜数据海洋:Java文件读写全面解析与实战指南
通过本文的详细解析与实战示例,您可以系统地掌握Java中各种文件读写操作,从基本的读写到高效的NIO操作,再到文件复制、移动和删除。希望这些内容能够帮助您在实际项目中处理文件数据,提高开发效率和代码质量。
242 4

热门文章

最新文章

推荐镜像

更多
  • DNS