@@ -101,6 +101,7 @@ Basic events:
101
101
lock
102
102
wall
103
103
itimer
104
+ ctimer
104
105
```
105
106
106
107
在 linux 下面
@@ -113,6 +114,7 @@ Basic events:
113
114
lock
114
115
wall
115
116
itimer
117
+ ctimer
116
118
Java method calls:
117
119
ClassName.methodName
118
120
Perf events:
@@ -314,31 +316,63 @@ profiler --cstack fp
314
316
315
317
此命令将收集 native 栈帧的 Frame Pointer 信息。
316
318
317
- ## 当指定 native 函数执行时开始/停止 profiling
319
+ ## 当指定 Native 函数执行时开始/停止 Profiling
318
320
319
- 使用 ` --begin function ` 和 ` --end function ` 选项在指定 native 函数被执行时让 profiling 过程启动或终止 。主要用途是分析特定的 JVM 阶段,比如 GC 和安全点 。需要使用特定 JVM 实现中的 native 函数名,比如 HotSpot JVM 中的 ` SafepointSynchronize::begin ` 和 ` SafepointSynchronize::end ` 。
321
+ 使用 ` --begin function ` 和 ` --end function ` 选项,可以在指定的 Native 函数被执行时启动或终止性能分析 。主要用途是分析特定的 JVM 阶段,比如 GC 和 Safepoint 。需要使用特定 JVM 实现中的 Native 函数名,比如在 HotSpot JVM 中的 SafepointSynchronize::begin 和 SafepointSynchronize::end。
320
322
321
- ### Time-to-safepoint profiling
323
+ ### Time-to-Safepoint Profiling
322
324
323
- 选项 ` --ttsp ` 实际上是 ` --begin SafepointSynchronize::begin --end RuntimeService::record_safepoint_synchronized ` 的一个别名。它是一种约束而不是独立的 event 类型。无论选择哪种 event,profiler 都可以正常工作,但只有 VM 操作和 safepoint request 之间的事件会被记录下来。
325
+ 选项 ` --ttsp ` 实际上是 ` --begin SafepointSynchronize::begin --end RuntimeService::record_safepoint_synchronized ` 的一个别名。它是一种约束,而不是独立的事件类型。无论选择哪种事件,Profiler 都可以正常工作,但只有在 VM 操作和 Safepoint 请求之间的事件会被记录下来。
326
+
327
+ 现在,当使用 ` --ttsp ` 选项并指定 JFR 输出格式时,` profiler ` 会在生成的 JFR 文件中自动包含 profiler.Window 事件。这些事件表示每次 Time-to-Safepoint 暂停的时间区间,使您无需依赖 JVM 日志即可分析这些暂停。
328
+
329
+ 示例
324
330
325
331
``` bash
326
332
profiler start --begin SafepointSynchronize::begin --end RuntimeService::record_safepoint_synchronized
327
- profiler --ttsp
333
+ profiler start --ttsp --format jfr
328
334
```
329
335
336
+ 生成的 JFR 文件将包含 profiler.Window 事件,可以使用 JDK Mission Control 等工具查看和分析这些事件。
337
+
338
+ ** 注意事项:**
339
+
340
+ - profiler.Window 事件是通用的事件,适用于任何使用 --begin 和 --end 触发器的时间窗口,不仅限于 Safepoint 暂停。
341
+
342
+ - 在分析长时间的 Safepoint 暂停时,profiler.Window 事件可帮助您识别造成延迟的原因。
343
+
344
+ - 当使用 --ttsp 选项时,请确保使用 JFR 输出格式,以便能够生成并查看 profiler.Window 事件。
345
+
330
346
## 使用 profiler 记录的 event 生成 JFR 文件
331
347
332
348
用 ` --jfrsync CONFIG ` 选项可以指定配置启动 Java Flight Recording,输出的 jfr 文件会包含所有常规的 JFR event,但采样的来源是由 profiler 提供的。
333
349
334
- ` CONFIG ` 选项可以是 ` profile ` ,表示使用在 ` $JAVA_HOME/lib/jfr ` 目录下预置的“profile”配置,也可以是自定义的 JFR 配置文件(.jfc),此选项的值采用与 [ JFR.start 命令的 settings 选项] ( https://docs.oracle.com/en/java/javase/17/docs/specs/man/jcmd.html ) 相同的格式。
350
+ CONFIG 参数:
351
+
352
+ - 预置配置:CONFIG 可以是 profile,表示使用 $JAVA_HOME/lib/jfr 目录下预置的 profile 配置。
353
+ - 自定义配置文件:CONFIG 也可以是自定义的 JFR 配置文件(.jfc),此选项的值采用与 jcmd JFR.start 命令的 settings 选项相同的格式。
354
+ - 指定 JFR 事件列表:现在,可以直接在 --jfrsync 中指定要启用的 JFR 事件列表,而无需创建 .jfc 文件。要指定事件列表,请以 + 开头,多个事件用 + 分隔。
335
355
336
- 比如,以下命令使用“profile”配置启动 JFR:
356
+ 示例:
357
+
358
+ 使用预置的 profile 配置启动 JFR:
337
359
338
360
``` bash
339
361
profiler start -e cpu --jfrsync profile -f combined.jfr
340
362
```
341
363
364
+ 直接指定 JFR 事件列表,例如启用 jdk.YoungGarbageCollection 和 jdk.OldGarbageCollection 事件:
365
+
366
+ ``` bash
367
+ profiler start -e cpu --jfrsync +jdk.YoungGarbageCollection+jdk.OldGarbageCollection -f combined.jfr
368
+ ```
369
+
370
+ ** 注意事项**
371
+
372
+ - 当指定事件列表时,由于逗号 , 用于分隔不同的选项,因此事件之间使用加号 + 分隔。
373
+ - 如果 --jfrsync 参数不以 + 开头,则被视为预置配置名或 .jfc 配置文件的路径。
374
+ - 直接指定事件列表在目标应用运行在容器中时特别有用,无需额外的文件操作。
375
+
342
376
## 周期性保存结果
343
377
344
378
使用 ` --loop TIME ` 可以持续运行 profiler 并周期性保存结果。选项格式可以是具体时间 hh:mm: ss 或以秒、分钟、小时或天计算的时间间隔。需要确保指定的输出文件名中包含时间戳,否则每次输出的结果都会覆盖上次保存的结果。以下命令持续执行 profiling 并将每个小时内的记录保存到一个 jfr 文件中。
@@ -369,3 +403,117 @@ Linux 平台: 这个新功能仅在 Linux 平台上有效。macOS 上的 CPU 分
369
403
``` bash
370
404
profiler start -e cpu -i 10 --wall 100 -f out.jfr
371
405
```
406
+
407
+ ## ` ctimer ` 事件
408
+
409
+ ` ctimer ` 事件是一种新的 CPU 采样模式,基于 ` timer_create ` ,提供了无需 ` perf_events ` 的精确 CPU 采样。
410
+
411
+ 在某些情况下,` perf_events ` 可能不可用,例如由于 ` perf_event_paranoid ` 设置或 ` seccomp ` 限制,或者在容器环境中。虽然 itimer 事件可以在容器中工作,但可能存在采样不准确的问题。
412
+
413
+ ` ctimer ` 事件结合了 ` cpu ` 和 ` itimer ` 的优点:
414
+
415
+ - 高准确性:提供精确的 CPU 采样。
416
+ - 容器友好:默认在容器中可用。
417
+ - 低资源消耗:不消耗文件描述符。
418
+
419
+ ** 请注意,` ctimer ` 事件目前仅在 ` Linux ` 上支持,不支持 ` macOS ` 。**
420
+ 可参考 [ async-profiler Github Issues] ( https://github.com/async-profiler/async-profiler/issues/855 ) 了解更多信息。
421
+
422
+ 示例:
423
+
424
+ ``` bash
425
+ profiler start -e ctimer -o jfr -f ./out-test.jfr
426
+ ```
427
+
428
+ ## ` vtable ` 特性
429
+
430
+ 在某些应用程序中,大量的 CPU 时间花费在调用 ` megamorphic ` 的虚方法或接口方法上,这在性能分析中显示为 ` vtable stub ` 或 ` itable stub ` 。这无法帮助我们了解特定调用点为何是` megamorphic ` 以及如何优化它。
431
+
432
+ vtable 特性可以在` vtable stub ` 或 ` itable stub ` 之上添加一个伪帧,显示实际调用的对象类型。这有助于清楚地了解在特定调用点,不同接收者的比例。
433
+
434
+ 该特性默认禁用,可以通过 ` -F vtable ` 选项启用(或使用 ` features=vtable ` )。
435
+ 可参考 [ async-profiler Github Issues] ( https://github.com/async-profiler/async-profiler/issues/736 ) 了解更多信息。
436
+
437
+ 示例:
438
+
439
+ ``` bash
440
+ profiler start -F vtable
441
+ ```
442
+
443
+ ## ` comptask ` 特性
444
+
445
+ ` profiler ` 采样 JIT 编译器线程以及 Java 线程,可以显示 JIT 编译所消耗的 CPU 百分比。然而,Java 方法的编译资源消耗各不相同,了解哪些特定的 Java 方法在编译时消耗最多的 CPU 时间非常有用。
446
+
447
+ ` comptask ` 特性可以在 ` C1/C2 ` 的堆栈跟踪中添加一个虚拟帧,显示当前正在编译的任务,即正在编译的 Java 方法。
448
+
449
+ 该特性默认禁用,可以通过` -F comptask ` 选项启用(或使用 ` features=comptask ` )。
450
+ 可参考 [ async-profiler Github Issues] ( https://github.com/async-profiler/async-profiler/issues/777 ) 了解更多信息。
451
+
452
+ 示例:
453
+
454
+ ``` bash
455
+ profiler start -F comptask
456
+ ```
457
+
458
+ ## 配置替代的分析信号
459
+
460
+ ` profiler ` 使用 ` POSIX ` 信号来进行性能分析。默认情况下,` SIGPROF ` 用于 ` CPU ` 分析,` SIGVTALRM ` 用于 ` Wall-Clock ` 分析。然而,如果应用程序也使用这些信号,或者希望同时运行多个 ` profiler ` 实例,这可能会导致信号冲突。
461
+
462
+ 现在,可以使用 ` signal ` 参数来配置用于分析的信号,以避免冲突。
463
+ 可参考 [ async-profiler Github Issues] ( https://github.com/async-profiler/async-profiler/issues/759 ) 了解更多信息。
464
+
465
+ 语法
466
+
467
+ ``` bash
468
+ profiler start --signal < 信号号码>
469
+ ```
470
+
471
+ 如果需要分别指定 CPU 和 Wall-Clock 分析的信号,可以使用以下语法:
472
+
473
+ ``` bash
474
+ profiler start --signal < CPU信号号码> /< Wall信号号码>
475
+ ```
476
+
477
+ ## ` --clock ` 选项
478
+
479
+ ` --clock ` 选项允许用户控制用于采样时间戳的时钟源。这对于需要将 ` profiler ` 的数据与其他工具的数据进行时间戳对齐的场景非常有用。
480
+
481
+ 用法
482
+
483
+ ``` bash
484
+ profiler start --clock < tsc| monotonic>
485
+ ```
486
+
487
+ 参数
488
+
489
+ - ` tsc ` :使用 CPU 的时间戳计数器(` RDTSC ` )。这是默认选项,提供高精度的时间戳。
490
+ - ` monotonic ` :使用操作系统的单调时钟(` CLOCK_MONOTONIC ` )。这有助于在多种数据源之间对齐时间戳。
491
+ 可参考 [ async-profiler Github Issues] ( https://github.com/async-profiler/async-profiler/issues/723 ) 了解更多信息。
492
+
493
+ 示例 :
494
+
495
+ 使用 ` CLOCK_MONOTONIC ` 作为时间戳源:
496
+
497
+ ``` bash
498
+ profiler start --clock monotonic
499
+ ```
500
+
501
+ ** 注意事项:**
502
+
503
+ - 当需要将 ` profiler ` 的数据与其他使用 ` CLOCK_MONOTONIC ` 的工具(例如 ` perf ` )的数据进行对齐时,使用 ` --clock monotonic ` 。
504
+ - 在使用 ` jfrsync ` 模式时,请谨慎使用 ` --clock ` 选项,因为 JVM 和 ` profiler ` 可能使用不同的时间戳源,这可能导致结果不一致。
505
+
506
+ ## ` --norm ` 选项
507
+
508
+ 在 Java 20 及更早的版本中,编译器为 ` lambda ` 表达式生成的方法名称包含唯一的数字后缀。例如,同一代码位置定义的 ` lambda ` 表达式,可能会生成多个不同的帧名称,因为每个 ` lambda ` 方法的名称都会附加一个唯一的数字后缀(如 ` lambda$method$0 ` 、` lambda$method$1 ` 等)。这会导致逻辑上相同的堆栈无法在火焰图中合并,增加了性能分析的复杂性。
509
+
510
+ 为了解决这个问题,` profiler ` 新增了 ` --norm ` 选项,可以在生成输出时自动规范化方法名称,去除这些数字后缀,使相同的堆栈能够正确地合并。
511
+ 可参考 [ async-profiler Github Issues] ( https://github.com/async-profiler/async-profiler/issues/832 ) 了解更多信息。
512
+
513
+ ** 示例:**
514
+
515
+ 生成规范化的火焰图:
516
+
517
+ ``` bash
518
+ profiler start --norm
519
+ ```
0 commit comments