写点什么

性能测试中获取 JVM 资源信息

作者:FunTester
  • 2023-02-15
    北京
  • 本文字数:1995 字

    阅读完需:约 7 分钟

在以往性能测试中,通常施压机的硬件资源不会成为压力瓶颈,但是在多任务并行的场景中,如果一个任务占用当前机器资源过多,会影响其他任务执行。或者当前用例本身存在问题,导致性能无法进一步提升,影响了性能测试执行。


根据以上场景,如果能从监控工程上得到解决自然是最好的。可以实时监控施压机和施压进程的 CPU 占用、内存使用、GC 清空。但是,重点来了,并不是总能拥有一套完美的监控系统。这个时候,就需要自己手动解决一些痛点。


经过查阅资源,最终将方案锁定在java.lang.management.ManagementFactory这个类,看名字和路径大概能猜个七七八八了。以上我提到的信息都可以调用这个类的 API 获取。

CPU 使用率

下面分享一下如何获取当前 JVM 的 CPU 使用情况。


    static ThreadMXBean threadBean = ManagementFactory.getThreadMXBean()
static OperatingSystemMXBean osMxBean = ManagementFactory.getOperatingSystemMXBean()
static long lastSysTime = System.nanoTime()
static long lastUserTime = 0 /** * 获取最大进程数N,CPU使用率N*100% * @return */ static int getAvailableProcessors() { osMxBean.getAvailableProcessors() }
/** * 获取当前线程CPU使用率,最大100 * 已乘以100,已经除以了系统最大进程数 * @return */ static double getCpuUsage(boolean avg = true) { long totalTime = 0 for (long id : threadBean.getAllThreadIds()) { totalTime += threadBean.getThreadCpuTime(id) } long curtime = System.nanoTime() long usedTime = totalTime - lastUserTime long totalPassedTime = curtime - lastSysTime lastSysTime = curtime lastUserTime = totalTime def d = avg ? (((double) usedTime) / totalPassedTime / getAvailableProcessors()) * 100 : (((double) usedTime) / totalPassedTime) * 100 return d > 100 ? 8.88 : d }
复制代码


这里我用了一个参数,用来区分是否返回平均使用率还是返回总使用率之和。因为在 docker 环境中com.funtester.utils.OSUtil#getAvailableProcessors返回值着实让我很迷惑,至今还没懂其中奥妙。


下面分享获取系统负载的方法:


    /**     * 获取系统一分钟内的平均load     * @return     */    static def getLoad() {        osMxBean.getSystemLoadAverage() / getAvailableProcessors()    }
复制代码


同样的问题也存在这个方法中,但目前使用比较少,就没有做修改。

获取 GC 信息


static List<GarbageCollectorMXBean> gcMxBeans = ManagementFactory.getGarbageCollectorMXBeans();
/** * 获取GC信息{@link com.funtester.utils.OSUtil.GCInfo} * @return */ static def getGCinfo() { def infos = [] for (GarbageCollectorMXBean gcMxBean : gcMxBeans) { infos << new GCInfo(gcMxBean) } infos }
/** * GC信息类 */ static class GCInfo extends AbstractBean {
String name
int count
int time
GCInfo(String name, int count, int time) { this.name = name this.count = count this.time = time }
GCInfo(GarbageCollectorMXBean gcMxBean) { this.name = gcMxBean.getName() this.count = gcMxBean.getCollectionCount() this.time = gcMxBean.getCollectionTime() }
}
复制代码


这里只能算是个输出,很少用 GC 信息作为独立的依据。

其他

获取内存信息:


    /**     * 获取堆内存信息     * @return     */    static def heapMemInfo() {        memoryMXBean.getHeapMemoryUsage()    }
/** * 获取非堆内存信息 * @return */ static def noHeapMemInfo() { memoryMXBean.getNonHeapMemoryUsage() }
复制代码

使用场景

目前我的使用场景主要 2 个:


  1. 在本地执行性能测试场景中,将 JVM 信息定期输出,包含在性能测试数据取样的功能中。

  2. 在服务执行性能测试场景中,将 JVM 信息作为一个资源调配的指标。例如:CPU 资源占用过高,就降低一下对象池的活跃数据,主动回收一些资源。


在查阅资料的过程中,发现 SDK 的 API 很少能够直接获取硬件信息的,很多案例都是通过com.github.oshi:oshi-core:6.4.0这个类库实现的。看了一下文档,功能非常强大,有兴趣的可以直接上这个。


发布于: 刚刚阅读数: 2
用户头像

FunTester

关注

公众号:FunTester,800篇原创,欢迎关注 2020-10-20 加入

Fun·BUG挖掘机·性能征服者·头顶锅盖·Tester

评论

发布
暂无评论
性能测试中获取JVM资源信息_FunTester_InfoQ写作社区