JProfiler帮助文档

异常值检测与异常方法记录

在某些情况下,问题并不在于方法的平均调用时间,而是在于方法偶尔会出现异常。在调用树(call tree)中,所有方法调用都会累加,因此一个被频繁调用的方法即使每 10000 次调用中出现一次耗时为预期 100 倍的情况,也不会在总时间中留下明显的痕迹。

为了解决这个问题,JProfiler 在调用树中提供了异常值检测视图(outlier detection view)和异常方法记录(exceptional method recording)功能。

异常值检测视图

异常值检测视图显示了每个方法的调用持续时间和调用次数信息,以及单次调用所测得的最大时间。最大调用时间与平均时间的偏差反映了所有调用持续时间是处于狭窄的范围内,还是存在显著的异常值(outlier)。按如下公式计算的异常值系数:

(最大时间 - 平均时间) / 平均时间

有助于您在这方面对方法进行量化评估。默认情况下,表格按异常值系数降序排序,系数最高的方法排在最上方。如果已记录 CPU 数据,则异常值检测视图中的数据可用。

为了避免仅被调用几次的方法以及运行时间极短的方法造成过多干扰,可以在视图设置中为最大时间和调用次数设置下限阈值。默认情况下,异常值统计中仅显示最大时间超过 10 ms 且调用次数大于 10 的方法。

配置异常方法记录

一旦确定了存在异常调用耗时的方法,您可以在上下文菜单中将其添加为异常方法(exceptional method)。相同的上下文菜单操作也可在调用树视图中使用。

当您注册一个方法以进行异常方法记录时,最慢的几次调用将单独保留在调用树中。其他调用将照常合并到单个方法节点(node)中。单独保留的调用次数可以在配置文件设置(profiling settings)中进行配置。默认情况下,该值设置为 5。

在区分较慢的方法调用时,必须使用特定的线程状态进行时间测量。这不能使用 CPU 视图中的线程状态选择,因为那只是一个显示选项,而不是记录选项。默认情况下使用挂钟时间(Wall clock time),但可以在配置文件设置中配置不同的线程状态。相同的线程状态也会用于异常值检测视图。

在会话设置(session settings)中,您可以在脱离调用树或异常值检测视图上下文的情况下移除异常方法或添加新异常方法。此外,异常方法配置还提供了为常见系统(例如 AWT 和 JavaFX 事件分发机制,在这些机制中异常耗时的事件是一个主要问题)添加异常方法定义的选项。

调用树中的异常方法

异常运行(Exceptional Run)在调用树视图中的显示方式有所不同。

拆分后的方法节点具有修改后的图标,并显示附加文本:

  •  [exceptional run](异常运行)
    此类节点包含一次异常缓慢的方法运行。根据定义,其调用次数为 1。如果后续有许多其他方法运行耗时更长,根据配置的单独记录的方法运行的最大数量,该节点可能会消失并被添加到“[merged exceptional runs]”(合并异常运行)节点中。
  •  [merged exceptional runs](合并异常运行)
    未被判定为异常缓慢的方法调用将合并到此节点中。对于任何调用栈(call stack),每个异常方法只能有一个此类节点。
  •  [current exceptional run](当前异常运行)
    如果在调用树视图传输到 JProfiler GUI 时某个调用正在进行中,则此时尚无法确定该调用是否异常缓慢。“[current exceptional run]”(当前异常运行)显示为当前调用单独维护的树。调用完成后,它将作为单独的“[exceptional run]”(异常运行)节点保留,或者合并到“[merged exceptional runs]”(合并异常运行)节点中。

与通过探针(probe)和拆分方法进行的调用树拆分(call tree splitting)一样,异常方法节点在上下文菜单中提供了一个 Merge splitting level(合并拆分级别) 操作,让您可以动态合并和取消合并所有调用。