文档章节

关于【JVM Performance Counters】的实现

tivenwang
 tivenwang
发布于 2016/12/10 14:18
字数 1076
阅读 42
收藏 0

    在Java内置工具包tools.jar(一)sun.tools.jstack.Jps中我们谈到,jps工具的数据来源自hsperfdata_xxx目录下的文件中。其实,除了jps还有jstat以及基于此命令之上提供的jstatd、visualgc工具,数据来源均基于JVM Performance Counters输出的文件中,在JVM中该文件被称为PerfData。PerfData中记录了JVM运行时刻gc、编译器、classLoder、操作系统、线程等的状态数据,对于分析jvm运行状态非常重要。
      从头开始,在JVM初始化函数中,我们看到初始化全局数据中执行了perfMemory_init()方法:

void vm_init_globals() {
  check_ThreadShadow();
  basic_types_init();
  eventlog_init();
  mutex_init();
  chunkpool_init();
  perfMemory_init();
}
void perfMemory_init() {
  if (!UsePerfData) return;
  PerfMemory::initialize();
}
// create the PerfData memory region
//
// This method creates the memory region used to store performance
// data for the JVM. The memory may be created in standard or
// shared memory.
//
void PerfMemory::create_memory_region(size_t size) {

  if (PerfDisableSharedMem) {
    // do not share the memory for the performance data.
    _start = create_standard_memory(size);
  }
  else {
    _start = create_shared_memory(size);
    if (_start == NULL) {

      // creation of the shared memory region failed, attempt
      // to create a contiguous, non-shared memory region instead.
      //
      if (PrintMiscellaneous && Verbose) {
        warning("Reverting to non-shared PerfMemory region.\n");
      }
      PerfDisableSharedMem = true;
      _start = create_standard_memory(size);
    }
  }

  if (_start != NULL) _capacity = size;
}

也就是PerfData的初始化,其中UsePerfData控制了是否使用该特性。

-XX:+UsePerfData:Enables the perfdata feature. This option is enabled by default to allow JVM monitoring and performance testing. Disabling it suppresses the creation of the hsperfdata_userid directories. To disable the perfdata feature, specify -XX:-UsePerfData.

PerfMemory的初始化在不同的操作系统有不同的实现,我们仍以Linux为例,jvm需要申请一份内存在存储这份数据,从代码中可以看到我们有两种选择:create_shared_memory 和create_standard_memory,共享模式的内存即使用文件hsperfdata_xxx来给不同的用户/进程来读取,该文件同时使用mmap的方式将内容映射到内存中。私有模式即申请普通内存,此时外部进程无法读取内存数据,所以基于此数据的命令都将失效(jps/jstat等),另外需要注意的是在共享模式申请内存(同时可以理解为创建文件)失败时会转换为私有模式。这里又来了一个JVM参数PerfDisableSharedMem,默认我们使用的jdk都是false使用共享模式,但我们仍可以使用参数来控制这个行为。

product(bool, PerfDisableSharedMem, false,"Store performance data in standard memory")

        那么,存储性能数据的内存空间已经申请完毕,接下来如何收集数据?Performance Counters定义了一些它数据来源的nameSpace,如下代码所示。

/* jvmstat global and subsystem counter name space - enumeration value
 * serve as an index into the PerfDataManager::_name_space[] array
 * containing the corresponding name space string. Only the top level
 * subsystem name spaces are represented here.
 */
enum CounterNS {
  // top level name spaces
  JAVA_NS,
  COM_NS,
  SUN_NS,
  // subsystem name spaces
  JAVA_GC,              // Garbage Collection name spaces
  COM_GC,
  SUN_GC,
  JAVA_CI,              // Compiler name spaces
  COM_CI,
  SUN_CI,
  JAVA_CLS,             // Class Loader name spaces
  COM_CLS,
  SUN_CLS,
  JAVA_RT,              // Runtime name spaces
  COM_RT,
  SUN_RT,
  JAVA_OS,              // Operating System name spaces
  COM_OS,
  SUN_OS,
  JAVA_THREADS,         // Threads System name spaces
  COM_THREADS,
  SUN_THREADS,
  JAVA_PROPERTY,        // Java Property name spaces
  COM_PROPERTY,
  SUN_PROPERTY,
  NULL_NS,
  COUNTERNS_LAST = NULL_NS
};

在JVM运行期间,通过调用PerfDataManager保持时刻记录这些运行数据,它提供一系列的接口供收集性能数据,我们以查找调用方的方式可以看到StatSampler是触发数据收集的函数,它在Thread::create_vm()时创建的一个守护线程,在engage()中看到它的初始化伴随一个JVM参数PerfDataSamplingInterval:默认50秒执行一次去counter数据。

product(intx, PerfDataSamplingInterval, 50 /*ms*/,"Data sampling interval in milliseconds")

至此,性能数据就源源不断的采集下来,我们回顾一下整个流程:

1、启动jvm,初始化perfData内存。包含共享内存和普通内存申请。共享内存涉及映射文件的创建位置等逻辑。
2、一个线程启动,均会初始化StatSampler,以PerfDataSamplingInterval的频率采集数据至perfData中。
3、perfData汇总数据存储在内存中,在共享内存模式下以mmap方式映射到文件中。
4、文件可被其他进程/用户读取。

以数据流的方式来理解,其实并没有什么高深之处,数据的收集需要各个运行模块配合采集。这样就完成了Performance Counters的功能,这些数据能够在我们排查性能问题、处理故障时发挥巨大作用。

© 著作权归作者所有

共有 人打赏支持
tivenwang
粉丝 1
博文 14
码字总数 13424
作品 0
浦东
程序员
Java应用性能分析工具:async-profiler

作者: 一字马胡 转载标志 【2017-12-15】 更新日志 厉害的内容 及时对项目进行性能检测,并且分析检测结果数据,发现热点代码是一项充满意义的工作,因为可能因为某一段热点代码会拖慢整个系...

疼丸李白
2017/12/15
0
0
9 个帮助你进行Java性能调优的工具

NetBeans Profiler NetBeans Profiler is found in NetBeans The NetBeans profiler is a modular add on which is used to provide the profiling functionality for the NetBeans IDE, whi......

ihaolin
2014/06/16
0
0
IBM和SAP开源其JVM诊断工具

IBM最近发布了其Java诊断工具套件,该套件包含如下工具:面向Java的产品转储分析器(Dump Analyzer)、处理垃圾收集(GC,即Garbage Collection)的Extensible Verbose Toolkit和Java锁分析器...

JavaGG
2010/03/24
0
0
ByteBuffer.allocate() vs. allocateDirect

Operating systems perform I/O operations on memory areas. These memory areas, as far as the operating system is concerned, are contiguous sequences of bytes. It's no surprise th......

pczhangtl
2014/03/30
0
0
JDK 9 中有哪些 jmod 文件?

JDK 9 jmods 目录中有97个jmod文件,这些文件都是干嘛的呢?我们在写代码的时候,都应该怎么用呢? 「Project Jigsaw,或者说Java Modularity想要解决的问题,其实在它的项目官网上有非常精确...

程序员诗人
2017/09/23
0
0

没有更多内容

加载失败,请刷新页面

加载更多

linux使用ntfs-3g操作ntfs格式硬盘

Linux内核目前只支持对微软NTFS文件系统的读取。 NTFS-3G 是微软 NTFS 文件系统的一个开源实现,同时支持读和写。NTFS-3G 开发者使用 FUSE 文件系统来辅助开发,同时对可移植性有益。 安装 ...

linuxprobe16
43分钟前
1
0
kubeadm部署kubernetes集群

一、环境要求 这里使用RHEL7.5 master、etcd:192.168.10.101,主机名:master node1:192.168.10.103,主机名:node1 node2:192.168.10.104,主机名:node2 所有机子能基于主机名通信,编辑...

人在艹木中
今天
7
0
Shell特殊符号总结以及cut,sort,wc,uniq,tee,tr,split命令

特殊符号总结一 * 任意个任意字符 ? 任意一个字符 # 注释字符 \ 脱义字符 | 管道符 # #号后的备注被忽略[root@centos01 ~]# ls a.txt # 备注 a.txt[root@centos01 ~]# a=1[root@centos01...

野雪球
今天
2
0
OSChina 周二乱弹 —— 程序员圣衣

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @达尔文:分享Skeeter Davis的单曲《The End of the World》 《The End of the World》- Skeeter Davis 手机党少年们想听歌,请使劲儿戳(这里...

小小编辑
今天
16
0
[ python import module ] 导入模块

import moudle_name ----> import module_name.py ---> import module_name.py文件路径 -----> sys.path (这里进行查找文件) # from app.web import Personimport app.web.Person as Pe......

_______-
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部