PCGen的垃圾收集分析

介绍

我决定结合我的两个软件爱好,并在PCGen上进行一些分析, PCGen是一种流行的基于Java的开放源代码角色生成器,用于角色扮演游戏。 我用Censum ,我们( jClarity的)新的垃圾收集日志分析工具来进行分析。

本文假定您对JVM上的垃圾回收(GC)有所了解。 如果您不熟悉GC,那么建议您加入我们的jClarity朋友计划 。 我们正在建立有关GC的知识库,以便与整个Java社区自由共享,我们非常希望您能对此进行验证!

项目

我正在使用的两个项目是PCGen(我正在对其进行分析的项目)和Censum(GC分析工具)。

PCGen

PCGen是针对d20角色扮演系统(例如《星球大战》和《龙与地下城》)的流行角色生成器和维护程序。 这是一个长期运行的项目(> 10年),由一个大型(约750,000 LOC)Java Swing桌面工具组成,该工具具有大量专有格式的数据文件。 免责声明:我是PCGen的主席。

PCGen是一个数据密集型工具。 为了驱动其规则引擎并满足响应式UI的要求(具有大量详细信息),许多此类数据已预先加载并保存在内存中。 用户过去曾报告以下问题。

  1. 在处理多个字符和/或高级字符时,经常会出现暂停。
  2. 创建高级别角色或创建的角色超过2个时,PCGen就会死亡。 更多精通技术的用户报告说,他们在pcgen日志文件中看到OutOfMemoryError。

为了减轻PCGen(6.0)最新版本中的这种不良性能,已经做了一些工作,因此我决定使用Censum来确定这些更改是否改善了性能。

森森

Censum是jClarity的新垃圾收集分析工具。 重点是使用功能强大的分析来处理原始日志数据,并为繁忙的开发人员(例如PCGen!的贡献者)快速提供简单的英语答案。 免责声明:我是jClarity的CTO。

Censum是一项对开放源代码项目免费的新产品,当然,如果您要购买副本,今天就可以获得免费的评估许可证 (单击Try Censum )!

TLDR –结论

我们有好消息,一些信息和坏消息。

好消息

积极的消息是,PCGen开头的默认堆设置(-Xms256m -Xmx512m)现在足够大小,足以保持PCGen的运行。 即使创建了第5个复杂字符,也没有OutOfMemoryError。

Censum显示,一旦运行了完整的GC(通常在创建了每个新字符之后),便会恢复很大一部分堆,并且每个字符占用大约25-50 MB的堆空间。 我们可以粗略地推断出,起始点(已加载数据)约为125MB,PCGen可以随时轻松地保持大约10-15个字符打开而不会崩溃。 对于一个总经理来说,这可能还不足以让他的哥布林部落开始运转,但是对于大多数常规聚会而言,这当然足够了!

坏消息

负面消息稍多的是Censum报告,PCGen的暂停时间相对较高,很可能是由于过早晋升而引起的。 提早升级过多会导致我们想要的存储速度更快地进入旧一代。 这可能会产生连锁反应,导致收集更多旧的基因组以及完整的GC,自然导致更长的停顿时间。 有关高暂停时间,过早升级以及PCGen可以做什么的更多详细信息,请参见完整的分析部分。

从这里到哪里?

PCGen可以遵循Censum的“权宜之计”建议,以改变年轻一代空间的大小。 通过使用-XX:NewSize标志并将其设置为〜256M,可以缓解高暂停时间的问题。

但是,PCGen的长期解决方案是继续减少其数据结构(特别是玩家角色的表示)的影响。 实际上,这是PCGen今天正在进行的项目!

技术设置

PCGen通常从具有默认堆设置-Xms256m和-Xmx512m的Shell脚本运行。 对该脚本进行了更改,以提供产生可分析的GC日志所需的最少标志集。 添加到java命令的标志是:

-verbose:gc -Xloggc:pcgen_gc.log -XX:+ PrintGCDetails -XX:+ PrintTenuringDistribution

  • -verbose:gc和-Xloggc:pcgen_gc.log生成基本日志,该日志输出到名为pcgen_gc.log的文件。
  • -XX:+ PrintGCDetails提供Censum执行分析所需的GC分配信息的绝对最小集。
  • 最后,-XX:+ PrintTenuringDistribution提供有关对象何时从年轻的世代空间(伊甸园,幸存者1和幸存者2)移动到旧世代空间(使用期限)的有用信息。

所有这些选项对正在运行的JVM几乎没有影响。 您应该始终在生产中启用这些功能!

PCGen在运行Mac OS 10.7.5的MBP上与Oracle Java 7u10一起运行,具有8GB RAM,256MB SSD驱动器和超线程双核2.8Ghz i7处理器。

PCGen活动

PCGen首先加载基本游戏模式和系统文件+基本UI来加载数据源。 下一步是让用户选择要加载的数据源(角色扮演游戏规则集)。 装有“怪兽”套装的流行SRD 3.5 (地牢和巨龙3.5e)已加载。

一个角色( Karianna )被逐级创建到第20个巫师中,该巫师具有满载的咒语,设备和熟悉的猫(在PCGen中实际上是第2个角色)。 此后添加了几个更复杂的角色,包括大龙蓝龙(大量数据!)。

分析

我将介绍最初的数据加载用例,然后介绍常规用法(创建字符)。

资料载入

我很好奇初始数据加载对内存的影响。 尽管使用具有PCGen的SSD驱动器可以缩短加载时间,但毫无疑问,这是项目目标! 这是Censum在GC之后在堆分配方面显示的内容。

如您所见,数据的初始加载在数据加载结束时导致了许多年轻的世代集合和一个旧的(永久的)GC事件。 堆使用率最高可攀升至约325MB,但在收集垃圾后,堆使用率又降至约100MB。 加载大约15本厚规则书的数据还不错!

但是,PCGen的数据加载有点像Web /应用程序服务器(例如Tomcat)的启动期。 就您的GC分析而言,通常最好将其排除在一次性启动之外,而不是分析正在运行的应用程序。

创建角色

创建Karianna并将她提升到20级需要填写13个主选项卡的详细信息〜20个子选项卡和大量数据! 还创建了另外4个字符,它们具有相似的复杂性,其中一些友好(猫很熟悉),而有些则不友好(大龙蓝龙)。

该过程的一些屏幕截图如下:

技能专长

设备

嵌入式字符表

Censum的分析

打开日志文件后,Censum立刻将我带到了“分析摘要”屏幕,该屏幕使我一目了然地了解了PCGen的垃圾回收的进行情况。

好消息

我立即知道:

  1. 我有正确的标志来收集足够的GC数据以进行分析以使其正常工作
  2. 我的GC吞吐量很好(PCGen花费时间在运行,而不是在进行垃圾收集)
  3. 没有讨厌
    System.gc()调用(通常不是很好的做法)。

信息新闻

内存利用率 (内存泄漏是其中的一个子集)和内存池大小是信息性的,因为日志尚未收集24小时的数据(建议的最小值是查看应用程序一个完整工作日的周期)。

坏消息

PCGen似乎具有高的暂停时间以及过早的升级问题。 让我们进一步深入探讨!

高暂停时间

高暂停时间是由于GC收集器必须暂停应用程序线程才能以安全的方式清理对象引用所致。 收集器必须扫描和清理的对象引用越多,暂停时间就越长! 最长的停顿通常是由完整的GC集合引起的,其中清理了整个Java堆(例如,年轻一代和老一代的空间都变得很满)。

作为一个用户,我注意到停顿了两次,还不足以真正打扰我,但我知道我的硬件非常好,而且这些停顿时间对于其他用户而言可能会更糟。

正如Censum指出的那样,暂停所花费的时间的0.15%并不是主要的问题,而是所关心的0.666秒的暂停时间。 但是,我记得最长的暂停时间可能来自PCGen中的初始数据加载。 为了与此相关,Censum提供了一张暂停时间图。

数据加载是最严重的违法行为,但是肯定的是,由于GC已满,因此对于每个创建的角色,每个角色创建点周围都有½秒的良好暂停。 在使用PCGen的情况下,再说一秒钟对我来说并不令人讨厌,但是正如Censum所示,完整的GC需要时间,因此PCGen应该减少完整的GC的数量。

在这种情况下,我们知道由于Censum给我们的另一个警告–提早升级,我们可能会得到比我们想要的更多的完整GC。

提早促销

提早提倡本质上是指应该在年轻一代空间中收集的对象在年龄增长之前就被提升到老一代空间中。 这个“年龄”被称为任职期限,它基于1980年代进行的软件研究和JVM的运行时启发式算法的结合。 由于以下原因,可能会提早升职:

  1. 创造新物体的速度淹没了年轻一代的空间
  2. 正在创建的对象太大,无法容纳年轻的一代空间。 例如大的连续内存块。

这具有对旧的发电空间施加压力的效果。 它的填充速度更快,因此会收集更多的旧基因组并最终出现完整的GC,从而导致更频繁的暂停时间。

当我去看看应该提升对象多长时间以及它们被提升多早时,我立即得到了答案。 “任期摘要”屏幕向我们显示了“任期阈值”设置为15(对象可以在年轻一代中存活约15个集合,然后自然提升为老一代)。 另请注意,过早地提升了100%的对象!

然后,我去看看何时提升对象。 Censum告诉我,大多数人几乎是在年轻一代就开始晋升的(Tenuring Threshold为1)。 该值向我表明,到达的对象对于当前的年轻一代而言太大。 但是,我仔细检查并确保对象分配不是很高,Censum告诉我,对象分配的峰值约为2.5GB / s,这仅是大约? 我的MBP的功能,所以我们可以了。

PCGen采取的步骤

PCGen团队的下一步将是查看jmap中的直方图之类的内容,以查看正在创建哪些大对象。 快速检查jmap输出意味着我知道我们有String(字符串),char和byte的大型(多MB)连续数组。

此时PCGen的一个选项是调整年轻一代空间的大小,以便使用
-XX:NewRatio或-XX:NewSize标志。 设置这两个值之一的大小将取决于从jmap用法中发现的结果。 在这种情况下,需要将-XX:NewSize设置为〜256M,以减少暂停次数。

但是,通常这不是一个很好的长期解决方案。 PCGen项目最好减少这些大的连续内存分配的使用。 由汤姆·帕克(Tom Parker)和詹姆斯·登普西(James Dempsey)领导,这正是PCGen团队正在做的事情,将庞大的内存结构从整体式的PlayerCharacter类中提取到了更灵活的较小方面。

摘要

令人惊奇的是,PCGen志愿者为6.0版本付出的辛勤工作为最终用户带来了实实在在的红利!

几年前,我追踪了PCGen用户在加载第25级Kobold Shaman时报告的30秒以上的暂停。 我花了几天的时间才发现这是一个GC /内存问题,因为我只有原始的GC日志文件(它们是多线程的,不确定的野兽)。 展望未来,我肯定会使用像Censum这样的工具来更快地解决这些问题,这意味着我可以继续为PCGen添加新功能!

如果您想解决棘手的GC问题,请不要忘记查看PCGen来满足d20角色扮演游戏的需求和Censum !

参考:来自我们的JCG合作伙伴 Martijn Verburg 的PCGen垃圾收集分析,网址为Are We There Yet博客。

翻译自: https://www.javacodegeeks.com/2013/01/garbage-collection-analysis-of-pcgen.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/370193.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

THINKPHP增删改查--(改)

1.CURD 控制器?>namespace Home\Controller;use Think\Controller;class CurdController extends Controller{ public function index(){ $db_student D(Student); $data_student $db_student->relation(true)->select();// dump($data_student); $this->assign…

Linux监控CPU关闭服务器,监控Linux服务器CPU和内存

利用脚本获取Linux服务器的CPU和内存。需要安装bc计算器yum install -y bc创建执行脚本计算CPU利用率,配置了5秒采样。执行脚本,5秒后输出采集日期|CPU负载|可用内存|总内存#!/bin/sh##echo user nice system idle iowait irq softirqCPULOG_1$(cat /pro…

springboot不会运行gc_SpringBoot 和JVM 调优(深度好文,建议收藏)

点击上方[全栈开发者社区]→右上角[...]→[设为星标⭐]项目调优作为一名工程师,项目调优这事,是必须得熟练掌握的事情。在SpringBoot项目中,调优主要通过配置文件和配置JVM的参数的方式进行。一、修改配置文件关于修改配置文件 application.p…

移动端原生js,css3实现轮播图

一、功能需求 1、自动播放2、滑动切换3、点击切换 二、思路分析 html代码&#xff1a; <div class"container">   <ul class"list clearfix">   <li class"item fl item5">图5</li>   <li class"item fl …

关于换行这个动作,win 和 mac 的实现

‘\r是回车&#xff0c;前者使光标到行首&#xff0c;&#xff08;carriage return&#xff09;\n是换行&#xff0c;后者使光标下移一格&#xff0c;&#xff08;line feed&#xff09;\r 是回车&#xff0c;return\n 是换行&#xff0c;newline对于换行这个动作&#xff1a;u…

你好骆驼:自动文件传输

Apache Camel在其主页上 &#xff08;以及Camel用户指南中 &#xff09;将其描述为“基于已知企业集成模式的通用开源集成框架”。 Camel框架基于《 企业集成模式 》一书&#xff0c;并提供了该书中描述的模式的实现 。 我看一下这篇文章中使用Camel的“ Hello World”类型示例…

Linux 常用命令二 pwd cd

一、pwd命令 显示整个路径名&#xff1a; wangwang:~$ pwd /home/wang 二、cd命令 切换到其他路径&#xff08;相对路径方式&#xff09;&#xff1a; wangwang:~$ cd workpalce/ wangwang:~/workpalce$ pwd /home/wang/workpalce 切换到其他路径&#xff08;绝对路径方式&…

3dobject用什么打开_第一次用开塞露是什么感觉?网友:像打开了新世界的大门

第一次用开塞露是什么感觉&#xff1f;网友:像打开了新世界的大门我妈说我小时候便秘去医院&#xff0c;医生给开了支开塞露&#xff0c;然后在医院的公厕里使用的&#xff0c;我妈的描述是:“要不是我手挪走的快点&#xff0c;就直接喷我手了”。。。。。。。。。。。。。。。…

linux root邮箱地址,linux – 如何将root的电子邮件转发到外部电子邮件地址?

我家里有一台小型服务器(Ubuntu 10.04),我想将root的电子邮件转发到我的gmail托管域,以获取安全通知,什么不是.我把所有东西都撕掉了,然后从头开始跑到other issues.我现在有sendmail工作,我可以发邮件到someexternal.com并收到邮件.但是,向/root/.forward添加地址实际上并不转…

RHEL6.4 xclock安装小记

http://blog.sina.com.cn/s/blog_623630d50101tc67.html转载于:https://www.cnblogs.com/Baronboy/p/7077911.html

Java 7中对String.substring的更改

众所周知&#xff0c;在您生成相同源字符串的许多子字符串的情况下&#xff0c;Java会优化子字符串操作。 它通过使用(value, offset, count)存储信息的方式来做到这一点。 请参阅以下示例&#xff1a; 在上图中&#xff0c;您会看到字符串“ Hello”和“ World&#xff01;”…

原生js创建模态框

1.效果图如下&#xff1a; 2.代码如下&#xff1a; <!DOCTYPE html><html><head><meta charset"UTF-8"><title>Test</title><style>#pageMask {visibility: hidden; position: absolute;left: 0px; top: 0px;width:…

python查询oracle数据库_python针对Oracle常见查询操作实例分析

本文实例讲述了python针对Oracle常见查询操作。分享给大家供大家参考&#xff0c;具体如下&#xff1a;1.子查询(难)&#xff1a;当进行查询的时候&#xff0c;发现需要的数据信息不明确&#xff0c;需要先通过另一个查询得到&#xff0c;此查询称为子查询&#xff1b;执行顺序…

按钮事件处理(3)

在进行gui编程时&#xff0c;我们最常使用的控件时按钮&#xff0c;在java中JButton类代表了按钮。它的类层次结构图是&#xff1a; java.lang.Object|_ java.awt.Component|_java.awt.Container|_javax.swing.JComponent|_javax.swing.AbstractButton|_javax.swing.JButton我们…

linux下I2C驱动发送IO时序,Linux I2C 驱动阅读的碰到的一些网上没有提到的东西

# re: Linux I2C 驱动阅读的碰到的一些网上没有提到的东西 回复 更多评论2009-04-11 13:39 by 初学都楼主&#xff0c;你好。我看了你那篇《Linux I2C核心、总线与设备驱动[转]》&#xff0c;让我明白了不少&#xff0c;不过我还是有些不明白的地方&#xff0c;想请教一下。我…

Java内存模型和优化

总览 许多多线程代码开发人员都熟悉这样的想法&#xff0c;即不同的线程可以对持有的值有不同的看法&#xff0c;这不是唯一的原因&#xff0c;即如果线程不安全&#xff0c;它可能不会看到更改。 JIT本身可以发挥作用。 为什么不同的线程看到不同的值&#xff1f; 当您有多个…

C_数组详解

数组&#xff1a; 一 一维数组 1.1 一维数组的定义: 类型符 数组名[常量表达式]; int a[10]; 说明: 1.数组的命名规则遵循标识符命名规则。 2.定义时需要指定元素的个数。方括号里的常量表达式表示元素的个数。 3.常量表达式中不能包含变量&#xff1b;如&#xff1a;int a[n];…

CSS节选——选择器

CSS&#xff0c;cascading style sheet&#xff0c;层叠样式表&#xff0c;请留意层叠概念。 css3为了区分伪类和伪元素&#xff0c;伪元素采用双冒号写法。 常见伪类——:hover,:link,:active,:target,:not(),:focus。 常见伪元素——::first-letter,::first-line,::before…

python游戏循环设置_Pygame:游戏循环前的初始菜单

我正在制作一个this game的版本&#xff0c;并尝试将起始菜单设置为&#xff1a;我的计划是先做surface.fill(overlaycolor)&#xff0c;然后将这个图像blitting到屏幕上。在一个while循环中。之后&#xff0c;在用户想玩(另一个问题除外)之后&#xff0c;我们将进入另一个whil…

vue.js基础知识篇(7):表单校验详解

目录 网盘 第12章:表单校验 1.npm安装vue-validator $ npm install vue-validator 代码示例: var Vuerequire("vue"); var VueValidatorrequire("vue-validator"); Vue.use(VueValidator); 2.直接使用script标签引入vue.js 要下载vue-validator&#xff0c…