本文分享了由Jaco-Ben Vosloo编写的关于AnyLogic的使用实践技巧,希望能为正在学习或使用AnyLogic的用户提供帮助。
在建模时,通常需要优化模型的性能。要么通过提高内存利用率要么提高CPU的利用率。
然而,仅通过代码审查或手动试错更改,几乎是不可能完成的。幸运的是,Java应用程序有一个特定的工具可以帮助您,让工作变得更轻松。
因此,对于如何使用分析器分析模型性能这一主题,我发布了由 2 篇文章组成的系列文,第1篇重点介绍了如何改善内存消耗和如何检测内存泄漏。 本文是其中的第2篇,主要介绍了如何分析和提高CPU性能。
下面让我们看一个改善分析和提高CPU性能的示例。
本期要点
本期要点
示例模型
如何查找性能问题
什么是可视虚拟机
如何使用Visual VM分析模型性能
如何提高性能
一
示例
让我们来看一下下面我们一个实习生开发的超级简单的仿真模型,作为更大规模仿真的起点。
我们有一些智能体,使用了“到时”变迁在6个不同的状态之间移动。这些可以代表rea-life中的不同对象,例如快速消费品公司的订单,其中订单在“等待批准”、“批准”或“拒绝”等状态之间移动。或者,它可以表示供应链中在“运输订单”、“故障”、“加油”等之间移动的卡车。
我们要求实习生记录每个州的智能体数量,并将其绘制在叠加时间图上。最近从我们之前的一篇博客文章中了解了lambda函数和非常有用的实用程序函数,他们决定使用findAll()函数,计算每个状态下的智能体数并绘制总数。
附言:如果您认为自己是AnyLogic 高级用户,您应该能够发现上述模型中的问题以及它将对您的模型性能产生的影响。 花点时间做一个预测——事后对您的预测结果发表评论。
该模型非常简单,我们计划对其进行大的改进,例如添加大量智能体、更多智能体逻辑以及一些分析功能。但在此之前,让我们快速运行一整年,并检查结果。
接下来。。。。
一切看起来都很好!模型仿真了全年,结果看起来合理。内存消耗非常小,小于200 MB。。。但是等等。。。看看执行速度(右下角)。。。超过1分钟来仿真一整年,我们甚至还没有开始为模型添加重要的细节!在我们将智能体的数量增加了一倍,并添加了大量的统计数据、逻辑和功能之后,我们究竟将如何运行该模型。。。。
二
查找性能问题
幸运的是,优化java应用程序性能已经存在很长时间了。我们不需要依靠我们的直觉或反复试验来尝试和优化我们的仿真模型。
有许多商业工具可用于Java应用程序评测,我更喜欢来自eJ Technologies的Jprofiler。然而,一开始你可能不想把钱花在一个你不知道如何使用的工具上。幸运的是,像Visual VM这样的免费应用程序可以在这里为Mac和Windows下载。
在Mac上安装
在Mac上,如果运行DMG安装程序,只需将应用程序拖动到应用程序文件夹。
此后,您只需从应用程序文件夹中运行应用程序。但是,您需要在运行Visual VM的机器上安装Java。您可以从各种来源下载Java版本,在这里可以找到Oracle的最新Java版本。
在Windows上安装
在Windows上,您需要解压缩visaulvm。将文件压缩到您选择的目录。
然后,您需要导航到visualvm_xxx->bin文件夹中的实际应用程序(其中xxx是版本号)
为了运行visual vm,您还需要在计算机上安装Java版本。您可以从各种来源下载Java版本,在这里可以找到Oracle的最新Java版本。
三
什么是可视虚拟机
VisualVM是一种可视化工具,集成了多个command‐line JDK工具和轻量级分析功能。它被设计用于生产和开发时,进一步增强了Java SE平台的监视和性能分析能力。
VisualVM使您能够监视、分析、获取线程转储和浏览堆转储。
启动应用程序时,VisualVM的主窗口打开。应用程序窗口默认显示在主窗口的左窗格中。应用程序窗口使您能够快速查看在本地和远程JVM上运行的Java应用程序。
四
使用Visual VM分析模型性能
使用以下步骤对应用程序执行性能进行分析,或观看此处的视频以获取逐步说明
1) 将模型运行到执行缓慢的点并暂停。在我们的例子中,这是在模型启动后的任何地方,因为整个模型的执行是相同的
2) 打开Visual VM应用程序。
3) 在左侧窗格中,您将看到两个应用程序链接到您的模型。AnyLogic数据库以及模型本身。
4) 双击与模型关联的应用程序,然后选择右侧窗格中的“monitor”选项卡
从概述统计数据中可以看出,我们使用的是零CPU,这在模型暂停时是有意义的。现在,您可以再次开始运行仿真。
根据您的机器配置,您将看到CPU使用率显著增加。
仅供参考:使用VisualVM Monitor视图监视应用程序
CPU使用率:此图表绘制了一段时间内的CPU使用率,用于指示模型需求何时使CPU过载
堆:堆图显示总堆大小和当前使用的堆数量。堆类似于内存
类:类图显示加载类和共享类总数的概述。
线程:线程图显示了应用程序JVM中活动线程和守护进程线程数量的概述。如果您想在特定时间点捕获和查看应用程序线程上的精确数据,可以使用VisualVM进行线程转储。
5) 导航到Sampler页面,并在Sample部分选择CPU按钮。等待几秒钟,让分析器记录统计信息,然后点击停止按钮。
仅供参考:CPU配置文件
CPU profiler显示方法级CPU性能(执行时间)的详细数据,显示每个方法的总执行时间和调用次数。在分析应用程序性能时,VisualVM对分析应用程序的所有方法进行测试。线程在进入方法时发出“method entry”事件,在退出方法时生成相应的“method exit”事件。这两个事件都包含时间戳。这些数据是实时处理的。
6)选择正确的线程
在线程文件器按钮中,取消选择“Show all threads”,并仅选择“AnyLogic Execution Thread”。
7)分析线程
如果我们扩展不同的线程,我们将看到只有两个函数占用了几乎所有的CPU时间“…Chart.updateData()”和“…TrasnsitionTimeOut.execute()”
如果我们展开这些,我们会发现第一个与我们在图表中绘制的值有关,第二个与状态图转换有关。
因为我们不能对模型中的转换做任何事情(不改变核心逻辑)。让我们关注一下update chart函数。
我们看到,在每次更新调用中,对于为我们要在图表中显示的特定智能体状态保存数据的每个数据库对象,findAll()函数是最终的罪魁祸首。
五
提高性能
现在我们确切地知道了问题所在,让我们看看是否可以:
a) 少调用此函数
b) 改善其内部性能
由于findAll()是一个AnyLogic内部函数,我们不能修改。所以我们只需调用该函数一次。与其每次我们想找出谁处于什么状态时都在整个智能体群体中循环,不如让我们循环一次,然后为每个状态统计总数。一旦我们遍历了所有这些数据,我们可以将每个状态的总数添加到数据集,就可以直接在图表使用数据集。
注意:如果你想了解更多关于switch语句或任何其他Java编码是如何工作的,请查看我们的Java for AnyLogic课程以了解更多信息。
如果我们现在运行模型,它将在大约30秒内完成,这是一个50%的改进!
对分析器的双重检查表明,83%的CPU时间是由状态图转换引起的,只有8%是由统计记录事件引起的。
六
示例模型下载