菜单
开源

Java

Java 性能分析器,与 Pyroscope 集成,为 Java 应用程序的性能分析提供全面解决方案。它提供实时洞察,使开发者能够有效地理解和优化他们的 Java 代码库。此工具对于提高应用程序响应速度、减少资源消耗以及在 Java 环境中确保卓越性能至关重要。

注意

有关每个语言支持的配置文件类型列表,请参阅 可用的配置文件类型

开始之前

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

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

将 Java 性能分析添加到您的应用程序

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

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

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

最新版本也可在 Maven Central 获取。

配置Java客户端

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

从应用程序的Java代码启动Pyroscope

首先,添加Pyroscope依赖项

maven
<dependency>
  <groupId>io.pyroscope</groupId>
  <artifactId>agent</artifactId>
  <version>0.15.0</version>
</dependency>
gradle
implementation("io.pyroscope:agent:0.15.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()
);

javaagent方式启动Pyroscope

要开始分析Java应用程序,请使用pyroscope.jarjavaagent运行应用程序

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

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

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

您可以将动态标签(标签)添加到分析数据中。这些标签可以在UI中过滤数据。

动态添加标签

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

您还可以将静态标签(标签)添加到分析数据中

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()
);

配置选项

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

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

标志描述
PYROSCOPE_AGENT_ENABLED启用代理。默认为true
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_CONFIGURATION_FILE设置额外的属性配置文件。默认值是pyroscope.properties
PYROSCOPE_BASIC_AUTH_USERHTTP基本认证用户名。默认值是"" - 空字符串,表示没有认证。
PYROSCOPE_BASIC_AUTH_PASSWORDHTTP基本认证密码。默认值是"" - 空字符串,表示没有认证。
PYROSCOPE_TENANT_IDpyroscope租户ID,作为X-Scope-OrgID HTTP头传递。默认值是"" - 空字符串,表示没有租户ID。
PYROSCOPE_HTTP_HEADERS以JSON格式提供的额外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_LABELSPYROSCOPE_EXPORT_COMPRESSION_LEVEL_JFR类似,但应用于动态标签部分。默认值设置为BEST_SPEED
PYROSCOPE_GC_BEFORE_DUMP一个布尔值,在设置为true时在转储配置文件之前执行System.gc()命令。此选项可能对实时分析有用,但默认禁用。

将数据发送到Pyroscope OSS或Grafana Cloud配置文件

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

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基本认证。将<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 分析的更多信息