【问题标题】:How to create a reusable instant (non-duration) Java FlightRecorder JFR event?如何创建可重用的即时(持续时间)Java Flight Recorder JFR 事件?
【发布时间】:2021-09-06 12:17:58
【问题描述】:

我正在努力添加自定义飞行记录器事件以跟踪我们的一些 KPI,并通过飞行记录转储将它们暴露出来。

一个令我头疼的问题是如何将事件标记为基于“即时”或“持续时间”的事件。

https://docs.oracle.com/javacomponents/jmc-5-4/jfr-runtime-guide/about.htm#JFRUH171

从我有限的测试来看,似乎在您稍后重用的事件上调用 commit(比如在 ThreadLocal 中)使得第二次和即将到来的对 commit 的调用包括结束时间戳和第二次提交和第一次提交之间的持续时间. 这并不真正适合我当前的用例,我对事件创建和提交调用之间的时间不感兴趣。

在我看来,如果你总是实例化新事件并省略调用 begin构造一个没有持续时间的事件 - 但出于性能原因,我宁愿避免由每次生成新事件并限制堆分配。

【问题讨论】:

    标签: java profiling jfr


    【解决方案1】:

    所有事件都是持续的,因为它们包含一个称为持续时间的字段。如果您调用commit() 而不调用begin()end(),则持续时间将设置为0。它将在文件中为每个事件添加一个字节,并且开销可以忽略不计。在缓存和重用事件实例时,不支持,但在某些场景下可以工作。

    推荐的方法是为每个事件创建一个对象。在大多数情况下,如果对象没有逃逸,JIT 能够消除分配。也就是把你正在使用事件对象的方法留在里面。

    此视频描述了禁用事件的流程,但一些优化也适用于启用的事件。 https://youtu.be/plYESjZ12hM?t=1126

    Escape analysis 可能会随着时间的推移而改进,并且将来可能会使用 primitive objects。在线程本地缓存中可能会成为一种反模式,尤其是在 virtual threads 即将推出的情况下)

    【讨论】:

    • 谢谢基尔!来自 Mikael 的视频是我见过的对逃逸分析和死代码消除的最佳解释,如果涉及自定义事件,我会喜欢更多最佳实践示例。 2 个后续问题: - 大多数自定义事件示例设置可变字段,而不是传递给事件构造函数。这是由于 JIT 消除最佳实践还是它们可以互换? - JVM 内部事件似乎使用EventHandlers 而不是实例方法来构造/提交事件。这样做是出于性能原因吗?我们是否应该在性能关键代码中争取类似的东西?
    • 设置字段而不是使用构造函数的一个原因是使用“if (event.shouldCommit()) { event.x = foo() 来保护昂贵的操作(不能完全消除) ; ... }" 在其他情况下,我不知道构造函数是否更快。当涉及到内部事件时,我们注意到 JIT 无法消除某些事件的分配(可能是由于异常处理)。 bugs.openjdk.java.net/browse/JDK-8187234 所以我们在 JDK 中有一些临时的 hack。
    • 好的,这是保持构造函数精简的一个好点。我通过询问缓存的EventType 是否启用它并延迟构建事件来解决这个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-08-15
    • 2021-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多