解释 VisualVM 回溯

Posted

技术标签:

【中文标题】解释 VisualVM 回溯【英文标题】:Interpreting a VisualVM backtrace 【发布时间】:2017-07-17 16:52:59 【问题描述】:

我正在 Mandelbrot Set 浏览器上进行 CPU 分析。出于某种原因,java.lang.PersistentHashMap$BitmapIndexedNode.find 使用了相当大比例的总 CPU 时间。当我对分析结果进行快照并获得方法的回溯时,我得到了:

我看到很多对BigDecimal 操作的引用。似乎BigDecimal 运营商在某些时候需要在PersistentHashMap 上调用find

我对回溯的解释正确吗?对find 的调用是BigDecimal 操作的结果,这意味着我对此无能为力吗?这对他们来说似乎是一件奇怪的事情。不过,我很难比clojure.lang.Numbers$BigDecimalOps 更深入地挖掘来验证这一点。

【问题讨论】:

【参考方案1】:

你的解释是正确的。加法、乘法、否定、除法和其他BigDecimal 操作最终会进行哈希映射查找。这些是取消引用*math-context* Var 的一部分。每次在 Clojure 中对两个 BigDecimal 对象执行算术运算时都会发生这种情况。除了切换到其他数字类型(例如double)之外,没有什么可以做的。

clojure.core/*math-context* 动态变量没有文档字符串。据我所知,它旨在保存一个java.math.MathContext 对象。 MathContext 对象可用于为 BigDecimal 操作指定精度和 rounding mode。如果绑定了*math-context*,则其值将传递给Java 运行时中的BigDecimal 方法,就像BigDecimal.add(BigDecimal augend, MathContext mc) 中一样。当*math-context* 未绑定时,BigDecimal 方法称为without passing a context。

问题中堆栈跟踪的相关部分是:

...
clojure.lang.PersistentHashMap.entryAt(Object)
clojure.lang.Var.getThreadBinding()
clojure.lang.Var.deref()
clojure.lang.Numbers$BigDecimalOps.add/multiply/..
...

一些指向 Clojure 源代码的指针:

*math-context* 变量defined *math-context* 在执行 BigDecimal addition 时取消引用。其他操作也会发生同样的情况 取消引用 Var 需要调用 getThreadBinding is looked up 内的哈希映射 getThreadBinding

【讨论】:

以上是关于解释 VisualVM 回溯的主要内容,如果未能解决你的问题,请参考以下文章

如何解释 visualvm cpu 示例和从中创建的快照之间的不一致?

为啥在 VisualVM 中 CPU 时间大于挂钟时间?

为啥 VisualVM 为 VisualVM 本身运行 50 个线程?

Java虚拟机性能管理神器 - VisualVM 入门

IDEA安装 VisualVM 及使用

[转]VisualVM 入门指南