菜单
开源

Java

Java Profiler 与 Pyroscope 集成,为 Java 应用提供全面的性能分析解决方案。它提供实时洞察,使开发者能够有效地理解和优化其 Java 代码库。此工具对于提高应用响应能力、降低资源消耗以及确保 Java 环境中的顶尖性能至关重要。

注意

有关每种语言支持的性能分析类型列表,请参阅可用性能分析类型

开始之前

要捕获和分析性能分析数据,您需要一个托管的 Pyroscope OSS 服务器或一个托管的带有 Grafana Cloud Profiles 的 Pyroscope 实例(需要免费的 Grafana Cloud 账户)。

Pyroscope 服务器可以是用于开发的本地服务器,也可以是用于生产的远程服务器。

为您的应用添加 Java 性能分析

Java 集成以单个 jar 文件(pyroscope.jar)或 Maven 包的形式分发。支持的平台包括

  • Linux on x64
  • Linux on ARM64
  • MacOS on x64
  • MacOS on ARM64

访问 GitHub发布页面下载最新版本的pyroscope.jar

最新版本也可在Maven Central上找到。

配置 Java 客户端

您可以从应用程序代码中启动 Pyroscope,或将其作为 javaagent 附加。

从应用 Java 代码启动 Pyroscope

首先,添加 Pyroscope 依赖项

maven
<dependency>
  <groupId>io.pyroscope</groupId>
  <artifactId>agent</artifactId>
  <version>0.18.0</version>
</dependency>
gradle
implementation("io.pyroscope:agent:0.18.0")

将以下代码添加到您的应用程序中

java
PyroscopeAgent.start(
  new Config.Builder()
    .setApplicationName("ride-sharing-app-java")
    .setProfilingEvent(EventType.ITIMER)
    .setFormat(Format.JFR)
    .setServerAddress("http://pyroscope-server:4040")
    .build()
);
spring
import io.pyroscope.javaagent.PyroscopeAgent;
import io.pyroscope.javaagent.config.Config;
import io.pyroscope.javaagent.EventType;
import io.pyroscope.http.Format;

@PostConstruct
public void init() {

    PyroscopeAgent.start(
    new Config.Builder()
        .setApplicationName("ride-sharing-app-java")
        .setProfilingEvent(EventType.ITIMER)
        .setFormat(Format.JFR)
        .setServerAddress("http://pyroscope-server:4040")
        // Optionally, if authentication is enabled, specify the API key.
        // .setBasicAuthUser("<User>")
        // .setBasicAuthPassword("<Password>")
        // Optionally, if you'd like to set allocation threshold to register events, in bytes. '0' registers all events
        // .setProfilingAlloc("0")
        .build()
    );
}

您还可以选择替换一些 Pyroscope 组件

java
PyroscopeAgent.start(
  new PyroscopeAgent.Options.Builder(config)
    .setExporter(snapshot -> {
      // Your custom export/upload logic may go here
      // It is invoked every 10 seconds by default with snapshot of
      // profiling data
    })
    .setLogger((l, msg, args) -> {
      // Your custom logging may go here
      // Pyroscope does not depend on any logging library
      System.out.printf((msg) + "%n", args);
    })
    .setScheduler(profiler -> {
      // Your custom profiling schedule logic may go here
    })
    .build()
);

将 Pyroscope 作为 javaagent 启动

要启动 Java 应用程序的性能分析,使用 pyroscope.jar javaagent 运行您的应用程序

shell
export PYROSCOPE_APPLICATION_NAME=my.java.app
export PYROSCOPE_SERVER_ADDRESS=http://pyroscope-server:4040

java -javaagent:pyroscope.jar -jar app.jar

向 Java 应用程序添加性能分析标签

您可以向性能分析数据添加动态标签 (labels)。这些标签可以在 UI 中过滤数据。

动态添加标签

java
Pyroscope.LabelsWrapper.run(new LabelsSet("controller", "slow_controller"), () -> {
  slowCode();
});

您还可以向性能分析数据添加静态标签 (labels)

java
Pyroscope.setStaticLabels(Map.of("region", System.getenv("REGION")));
// or with Config.Builder if you start pyroscope with PyroscopeAgent.start
PyroscopeAgent.start(new Config.Builder()
    .setLabels(mapOf("region", System.getenv("REGION")))
    // ...
    .build()
);

配置选项

当您将 Pyroscope 作为 javaagent 启动或通过 Config.build() 获取配置时,Pyroscope 会在多个来源中搜索配置:系统属性、环境变量和 pyroscope.properties。属性键与环境变量名称相同,但使用小写,下划线(_)被句点(.)替换。例如,PYROSCOPE_FORMAT 变为 pyroscope.format

Java 集成支持 JFR 格式以支持多个事件(JFR 是唯一支持 async-profiler多个事件的输出格式)。有几个环境变量定义了多事件配置的工作方式

标志描述
PYROSCOPE_AGENT_ENABLED启用代理。默认值为 true
PYROSCOPE_APPLICATION_NAME设置应用程序名称。如果未提供,将使用生成的名称。
PYROSCOPE_PROFILING_INTERVAL设置 CPU 性能分析的采样间隔。默认值为 10ms
PYROSCOPE_FORMAT设置性能分析器输出格式。默认值为 collapsed,但为了支持多种格式,必须将其设置为 jfr
PYROSCOPE_PROFILER_EVENT设置性能分析器事件。启用 JFR 格式后,此事件指代可能的 CPU 性能分析事件之一:itimercpuwall。默认值为 itimer
PYROSCOPE_PROFILER_ALLOC设置注册分配事件的阈值(以字节为单位)(等同于 async-profiler 中的 --alloc=)。默认值为 "" - 空字符串,这意味着分配性能分析已禁用。将其设置为 0 将注册每个事件,导致显著的 CPU 和网络开销,因此不适用于生产环境。我们建议将起始值设置为 512k,并根据需要进行调整。
PYROSCOPE_PROFILER_LOCK设置注册锁事件的阈值(以纳秒为单位)(等同于 async-profiler 中的 --lock=)。默认值为 "" - 空字符串,这意味着锁性能分析已禁用。将其设置为 0 将注册每个事件,导致显著的 CPU 和网络开销,因此不适用于生产环境。我们建议将起始值设置为 10ms,并根据需要进行调整。
PYROSCOPE_UPLOAD_INTERVAL设置上传性能分析数据的间隔。默认值为 10s
PYROSCOPE_JAVA_STACK_DEPTH_MAX设置最大堆栈深度。默认值为 2048
PYROSCOPE_SERVER_ADDRESSPyroscope 服务器地址。默认值为 https://:4040
PYROSCOPE_CONFIGURATION_FILE设置一个附加的属性配置文件。默认值为 pyroscope.properties
PYROSCOPE_BASIC_AUTH_USERHTTP Basic 身份验证用户名。默认值为 "" - 空字符串,无身份验证。
PYROSCOPE_BASIC_AUTH_PASSWORDHTTP Basic 身份验证密码。默认值为 "" - 空字符串,无身份验证。
PYROSCOPE_TENANT_IDPyroscope 租户 ID,作为 X-Scope-OrgID HTTP 头传递。默认值为 "" - 空字符串,无租户 ID。
PYROSCOPE_HTTP_HEADERSJSON 格式的额外 HTTP 头,例如:{"X-Header": "Value"}。默认值为 {} - 无额外头。
PYROSCOPE_LABELS设置逗号分隔的 key=value 对形式的静态标签。默认值为 "" - 空字符串,无标签。
PYROSCOPE_LOG_LEVEL确定 Pyroscope 日志记录器的详细程度。可用选项包括 debuginfowarnerror。默认值设置为 info
PYROSCOPE_PUSH_QUEUE_CAPACITY指定摄取队列的大小,该队列在网络中断期间临时存储内存中的性能分析数据。默认值设置为 8。
PYROSCOPE_INGEST_MAX_TRIES设置在失败时重试摄取 API 调用的最大次数。值为 -1 表示重试将无限期继续。默认值设置为 8
PYROSCOPE_EXPORT_COMPRESSION_LEVEL_JFR设置应用于上传的 JFR 文件的 GZIP 压缩级别。此选项接受值:NO_COMPRESSIONBEST_SPEEDBEST_COMPRESSIONDEFAULT_COMPRESSION
PYROSCOPE_EXPORT_COMPRESSION_LEVEL_LABELS功能类似于 PYROSCOPE_EXPORT_COMPRESSION_LEVEL_JFR,但应用于动态标签部分。默认值设置为 BEST_SPEED
PYROSCOPE_ALLOC_LIVE仅保留带有活动对象(在性能分析会话结束时未被回收的对象)的分配采样。对于查找 Java 堆内存泄漏非常有用。默认值为 false
PYROSCOPE_GC_BEFORE_DUMP一个布尔值,当设置为 true 时,在转储性能分析数据之前执行 System.gc() 命令。此选项可能对实时性能分析有用,但默认情况下是禁用的。

将数据发送到 Pyroscope OSS 或 Grafana Cloud Profiles

将以下代码添加到您的应用程序中

java
PyroscopeAgent.start(
    new Config.Builder()
        .setApplicationName("test-java-app")
        .setProfilingEvent(EventType.ITIMER)
        .setFormat(Format.JFR)
        .setServerAddress("<URL>")
        // Set these if using Grafana Cloud:
        .setBasicAuthUser("<User>")
        .setBasicAuthPassword("<Password>")
        // Optional Pyroscope tenant ID (only needed if using multi-tenancy). Not needed for Grafana cloud.
        // .setTenantID("<TenantID>")
        .build()
);

要配置 Java SDK 将数据发送到 Pyroscope,请将占位符 <URL> 替换为相应的服务器 URL。这可以是 Grafana Cloud URL 或您自己的自定义 Pyroscope 服务器 URL。

如果您需要将数据发送到 Grafana Cloud,则必须配置 HTTP Basic 身份验证。将 <User> 替换为您的 Grafana Cloud 堆栈用户,将 <Password> 替换为您的 Grafana Cloud API 密钥。

如果您的 Pyroscope 服务器启用了多租户,您需要配置租户 ID。将 <TenantID> 替换为您的 Pyroscope 租户 ID。

配置示例

以下配置设置了应用程序名称、Pyroscope 格式、性能分析间隔、事件和锁。此示例摘自 Pyroscope 仓库中可用的rideshare Dockerfile

ENV PYROSCOPE_APPLICATION_NAME=rideshare.java.push.app
ENV PYROSCOPE_FORMAT=jfr
ENV PYROSCOPE_PROFILING_INTERVAL=10ms
ENV PYROSCOPE_PROFILER_EVENT=itimer
ENV PYROSCOPE_PROFILER_LOCK=10ms

此配置片段启用了分配和锁性能分析

PYROSCOPE_PROFILER_ALLOC=512k
PYROSCOPE_PROFILER_LOCK=10ms

Java 性能分析示例

查看以下资源以了解更多关于 Java 性能分析的信息