mirror of
https://github.com/async-profiler/async-profiler.git
synced 2026-04-28 10:53:49 +00:00
Compare commits
5 Commits
8aab346c3b
...
v4.2.1-rc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f60b4d3ac | ||
|
|
e5582ad01f | ||
|
|
08866f6616 | ||
|
|
73622cc19e | ||
|
|
e7973af2ac |
@@ -1,6 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## [4.2] - Early Access
|
||||
## [4.2.1] - Maintenance Release
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- #1599: Workaround for the kernel PERF_EVENT_IOC_REFRESH bug
|
||||
- #1596: Do not block any signals during execution of a custom crash handler
|
||||
|
||||
## [4.2] - 2025-10-20
|
||||
|
||||
### Features
|
||||
|
||||
|
||||
2
Makefile
2
Makefile
@@ -1,4 +1,4 @@
|
||||
PROFILER_VERSION ?= 4.2
|
||||
PROFILER_VERSION ?= 4.2.1
|
||||
|
||||
ifeq ($(COMMIT_TAG),true)
|
||||
PROFILER_VERSION := $(PROFILER_VERSION)-$(shell git rev-parse --short=8 HEAD)
|
||||
|
||||
10
README.md
10
README.md
@@ -23,12 +23,12 @@ to learn about more features.
|
||||
|
||||
# Download
|
||||
|
||||
### Stable release: [4.1](https://github.com/async-profiler/async-profiler/releases/tag/v4.1)
|
||||
### Stable release: [4.2](https://github.com/async-profiler/async-profiler/releases/tag/v4.2)
|
||||
|
||||
- Linux x64: [async-profiler-4.1-linux-x64.tar.gz](https://github.com/async-profiler/async-profiler/releases/download/v4.1/async-profiler-4.1-linux-x64.tar.gz)
|
||||
- Linux arm64: [async-profiler-4.1-linux-arm64.tar.gz](https://github.com/async-profiler/async-profiler/releases/download/v4.1/async-profiler-4.1-linux-arm64.tar.gz)
|
||||
- macOS arm64/x64: [async-profiler-4.1-macos.zip](https://github.com/async-profiler/async-profiler/releases/download/v4.1/async-profiler-4.1-macos.zip)
|
||||
- Profile converters: [jfr-converter.jar](https://github.com/async-profiler/async-profiler/releases/download/v4.1/jfr-converter.jar)
|
||||
- Linux x64: [async-profiler-4.2-linux-x64.tar.gz](https://github.com/async-profiler/async-profiler/releases/download/v4.2/async-profiler-4.2-linux-x64.tar.gz)
|
||||
- Linux arm64: [async-profiler-4.2-linux-arm64.tar.gz](https://github.com/async-profiler/async-profiler/releases/download/v4.2/async-profiler-4.2-linux-arm64.tar.gz)
|
||||
- macOS arm64/x64: [async-profiler-4.2-macos.zip](https://github.com/async-profiler/async-profiler/releases/download/v4.2/async-profiler-4.2-macos.zip)
|
||||
- Profile converters: [jfr-converter.jar](https://github.com/async-profiler/async-profiler/releases/download/v4.2/jfr-converter.jar)
|
||||
|
||||
### Nightly builds
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
async-profiler provides `jfrconv` utility to convert between different profile output formats.
|
||||
`jfrconv` can be found at the same location as the `asprof` binary. Converter is also available
|
||||
as a standalone Java application: [`jfr-converter.jar`](https://github.com/async-profiler/async-profiler/releases/download/v4.1/jfr-converter.jar).
|
||||
as a standalone Java application: [`jfr-converter.jar`](https://github.com/async-profiler/async-profiler/releases/download/v4.2/jfr-converter.jar).
|
||||
|
||||
## Supported conversions
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ $ java -agentpath:/path/to/libasyncProfiler.so=start,event=cpu,file=profile.html
|
||||
|
||||
Agent library is configured through the JVMTI argument interface.
|
||||
The format of the arguments string is described
|
||||
[in the source code](https://github.com/async-profiler/async-profiler/blob/v4.1/src/arguments.cpp#L45).
|
||||
[in the source code](https://github.com/async-profiler/async-profiler/blob/v4.2/src/arguments.cpp#L39).
|
||||
`asprof` actually converts command line arguments to that format.
|
||||
|
||||
Another important use of attaching async-profiler as an agent is for continuous profiling.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>tools.profiler</groupId>
|
||||
<artifactId>jfr-converter</artifactId>
|
||||
<version>4.2</version>
|
||||
<version>4.2.1</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>async-profiler</name>
|
||||
|
||||
2
pom.xml
2
pom.xml
@@ -3,7 +3,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>tools.profiler</groupId>
|
||||
<artifactId>async-profiler</artifactId>
|
||||
<version>4.2</version>
|
||||
<version>4.2.1</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>async-profiler</name>
|
||||
|
||||
@@ -279,8 +279,9 @@ SigAction OS::replaceCrashHandler(SigAction action) {
|
||||
struct sigaction sa;
|
||||
sigaction(SIGSEGV, NULL, &sa);
|
||||
SigAction old_action = sa.sa_handler == SIG_DFL ? restoreSignalHandler : sa.sa_sigaction;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_sigaction = action;
|
||||
sa.sa_flags |= SA_SIGINFO | SA_RESTART;
|
||||
sa.sa_flags |= SA_SIGINFO | SA_RESTART | SA_NODEFER;
|
||||
sigaction(SIGSEGV, &sa, NULL);
|
||||
return old_action;
|
||||
}
|
||||
|
||||
@@ -247,14 +247,16 @@ SigAction OS::replaceCrashHandler(SigAction action) {
|
||||
|
||||
sigaction(SIGBUS, NULL, &sa);
|
||||
orig_sigbus_handler = sa.sa_handler == SIG_DFL ? restoreSignalHandler : sa.sa_sigaction;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_sigaction = action;
|
||||
sa.sa_flags |= SA_SIGINFO | SA_RESTART;
|
||||
sa.sa_flags |= SA_SIGINFO | SA_RESTART | SA_NODEFER;
|
||||
sigaction(SIGBUS, &sa, NULL);
|
||||
|
||||
sigaction(SIGSEGV, NULL, &sa);
|
||||
orig_sigsegv_handler = sa.sa_handler == SIG_DFL ? restoreSignalHandler : sa.sa_sigaction;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_sigaction = action;
|
||||
sa.sa_flags |= SA_SIGINFO | SA_RESTART;
|
||||
sa.sa_flags |= SA_SIGINFO | SA_RESTART| SA_NODEFER;
|
||||
sigaction(SIGSEGV, &sa, NULL);
|
||||
|
||||
// Return an action that dispatches to one of the original handlers depending on signo,
|
||||
|
||||
@@ -20,6 +20,7 @@ class PerfEvents : public CpuEngine {
|
||||
static int _max_events;
|
||||
static PerfEvent* _events;
|
||||
static PerfEventType* _event_type;
|
||||
static int _ioc_enable;
|
||||
static bool _alluser;
|
||||
static bool _kernel_stack;
|
||||
static bool _record_cpu;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <sys/resource.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include "arch.h"
|
||||
#include "fdtransferClient.h"
|
||||
@@ -153,6 +154,17 @@ static void adjustFDLimit() {
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround for the kernel bug: PERF_EVENT_IOC_REFRESH can hang
|
||||
// the entire system on Linux 6.16.x and 6.17.x.
|
||||
// See https://github.com/async-profiler/async-profiler/issues/1578
|
||||
static bool hasPerfEventRefreshBug() {
|
||||
static struct utsname u{};
|
||||
if (u.release[0] == 0 && uname(&u) != 0) {
|
||||
return false;
|
||||
}
|
||||
return strncmp(u.release, "6.16.", 5) == 0 || strncmp(u.release, "6.17.", 5) == 0;
|
||||
}
|
||||
|
||||
struct FunctionWithCounter {
|
||||
const char* name;
|
||||
int counter_arg;
|
||||
@@ -532,6 +544,7 @@ class PerfEvent : public SpinLock {
|
||||
int PerfEvents::_max_events = 0;
|
||||
PerfEvent* PerfEvents::_events = NULL;
|
||||
PerfEventType* PerfEvents::_event_type = NULL;
|
||||
int PerfEvents::_ioc_enable;
|
||||
bool PerfEvents::_alluser;
|
||||
bool PerfEvents::_kernel_stack;
|
||||
bool PerfEvents::_record_cpu;
|
||||
@@ -641,7 +654,7 @@ int PerfEvents::createForThread(int tid) {
|
||||
if (fcntl(fd, F_SETFL, O_ASYNC) < 0 || fcntl(fd, F_SETSIG, _signal) < 0 || fcntl(fd, F_SETOWN_EX, &ex) < 0) {
|
||||
err = errno;
|
||||
Log::warn("perf_event fcntl failed: %s", strerror(err));
|
||||
} else if (ioctl(fd, PERF_EVENT_IOC_RESET, 0) < 0 || ioctl(fd, PERF_EVENT_IOC_REFRESH, 1) < 0) {
|
||||
} else if (ioctl(fd, PERF_EVENT_IOC_RESET, 0) < 0 || ioctl(fd, _ioc_enable, 1) < 0) {
|
||||
err = errno;
|
||||
Log::warn("perf_event ioctl failed: %s", strerror(err));
|
||||
} else {
|
||||
@@ -697,6 +710,10 @@ void PerfEvents::signalHandler(int signo, siginfo_t* siginfo, void* ucontext) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_ioc_enable == PERF_EVENT_IOC_ENABLE) {
|
||||
ioctl(siginfo->si_fd, PERF_EVENT_IOC_DISABLE, 0);
|
||||
}
|
||||
|
||||
if (_enabled) {
|
||||
ExecutionEvent event(TSC::ticks());
|
||||
u64 counter = readCounter(siginfo, ucontext);
|
||||
@@ -706,7 +723,7 @@ void PerfEvents::signalHandler(int signo, siginfo_t* siginfo, void* ucontext) {
|
||||
}
|
||||
|
||||
ioctl(siginfo->si_fd, PERF_EVENT_IOC_RESET, 0);
|
||||
ioctl(siginfo->si_fd, PERF_EVENT_IOC_REFRESH, 1);
|
||||
ioctl(siginfo->si_fd, _ioc_enable, 1);
|
||||
}
|
||||
|
||||
void PerfEvents::signalHandlerJ9(int signo, siginfo_t* siginfo, void* ucontext) {
|
||||
@@ -715,6 +732,10 @@ void PerfEvents::signalHandlerJ9(int signo, siginfo_t* siginfo, void* ucontext)
|
||||
return;
|
||||
}
|
||||
|
||||
if (_ioc_enable == PERF_EVENT_IOC_ENABLE) {
|
||||
ioctl(siginfo->si_fd, PERF_EVENT_IOC_DISABLE, 0);
|
||||
}
|
||||
|
||||
if (_enabled) {
|
||||
u64 counter = readCounter(siginfo, ucontext);
|
||||
J9StackTraceNotification notif;
|
||||
@@ -726,7 +747,7 @@ void PerfEvents::signalHandlerJ9(int signo, siginfo_t* siginfo, void* ucontext)
|
||||
}
|
||||
|
||||
ioctl(siginfo->si_fd, PERF_EVENT_IOC_RESET, 0);
|
||||
ioctl(siginfo->si_fd, PERF_EVENT_IOC_REFRESH, 1);
|
||||
ioctl(siginfo->si_fd, _ioc_enable, 1);
|
||||
}
|
||||
|
||||
const char* PerfEvents::title() {
|
||||
@@ -830,6 +851,13 @@ Error PerfEvents::start(Arguments& args) {
|
||||
_alluser = strcmp(args._event, EVENT_CPU) != 0 && !supported();
|
||||
}
|
||||
|
||||
if (strcmp(_event_type->name, "cpu-clock") == 0 && hasPerfEventRefreshBug()) {
|
||||
Log::debug("Enable workaround for PERF_EVENT_IOC_REFRESH bug");
|
||||
_ioc_enable = PERF_EVENT_IOC_ENABLE; // opt-in for manual enable/disable
|
||||
} else {
|
||||
_ioc_enable = PERF_EVENT_IOC_REFRESH; // autodisable perf_event on counter overflow
|
||||
}
|
||||
|
||||
adjustFDLimit();
|
||||
|
||||
int max_events = OS::getMaxThreadId();
|
||||
|
||||
Reference in New Issue
Block a user