mirror of
https://github.com/async-profiler/async-profiler.git
synced 2026-04-28 10:53:49 +00:00
Compare commits
5 Commits
8aab346c3b
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5853965e4c | ||
|
|
d3e30d9d6a | ||
|
|
f6ca3c1ff8 | ||
|
|
86adc1605a | ||
|
|
804df3ac8e |
28
.github/workflows/compare-binary-sizes.yaml
vendored
Normal file
28
.github/workflows/compare-binary-sizes.yaml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
name: compare-binary-sizes
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: [CI]
|
||||
types: [completed]
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
actions: read
|
||||
env:
|
||||
GH_TOKEN: "${{ github.token }}"
|
||||
REPO: "${{ github.repository }}"
|
||||
PR_SHA: "${{ github.event.workflow_run.head_sha }}"
|
||||
jobs:
|
||||
compare:
|
||||
if: ${{ github.event.workflow_run.event == 'pull_request' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- run: |
|
||||
gh api "repos/${REPO}/contents/scripts/compare-binary-sizes.sh" -H 'Accept: application/vnd.github.raw' > compare.sh
|
||||
read pr base_sha < <(gh api "repos/${REPO}/commits/${PR_SHA}/pulls" --jq '.[0] | "\(.number) \(.base.sha)"')
|
||||
function find-archive() { find "${1}" -type f \( -name "async-profiler-*${2}.tar.gz" -o -name "async-profiler-*${2}.zip" \) ! -name '*-debug*' | head -n1; }
|
||||
for p in linux-x64 linux-arm64 macos; do
|
||||
gh run download -R "${REPO}" -n "async-profiler-${p}-${base_sha:0:7}" -D "base/${p}" 2>/dev/null || continue
|
||||
gh run download -R "${REPO}" -n "async-profiler-${p}-${PR_SHA:0:7}" -D "pr/${p}" 2>/dev/null || continue
|
||||
bash compare.sh "$(find-archive "base/${p}" "${p}")" "$(find-archive "pr/${p}" "${p}")" >> report.md
|
||||
done
|
||||
gh pr comment "${pr}" -R "${REPO}" --body-file report.md --edit-last --create-if-none
|
||||
@@ -1,6 +1,6 @@
|
||||
# Changelog
|
||||
|
||||
## [4.4]
|
||||
## [4.4] - 2026-04-20
|
||||
|
||||
### Features
|
||||
|
||||
@@ -27,15 +27,18 @@
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- #1727: Allocation profile has wrong units in OTLP format
|
||||
- #1716: Wall-clock Heatmap does not count samples correctly
|
||||
- #1715: Fix Zing crash when profiling cpu+wall together
|
||||
- #1708: Another fix for correct vDSO unwinding on ARM64
|
||||
- #1707: Workaround for JFR shutdown race
|
||||
- #1699: Allow negative keys in JFR constant pool
|
||||
- #1697: Ensure remaining buffer is sufficient for event data in JfrReader
|
||||
- #1657: Re-enable workaround for a long attach on JDK 8
|
||||
- #1654: Prefer perf-events engine when record-cpu or target-cpu are selected
|
||||
- #1585: Scale perf counters in case of multiplexing
|
||||
- #1528: Add a hard-coded limit on the maximum number of jmethodIDs
|
||||
- #1203: Fix "Instance field not found" when using `-Xcheck:jni` on JDK 8
|
||||
- Do not walk past virtual thread continuation barriers
|
||||
|
||||
## [4.3] - 2026-01-20
|
||||
|
||||
10
README.md
10
README.md
@@ -23,12 +23,12 @@ to learn about more features.
|
||||
|
||||
# Download
|
||||
|
||||
### Stable release: [4.3](https://github.com/async-profiler/async-profiler/releases/tag/v4.3)
|
||||
### Stable release: [4.4](https://github.com/async-profiler/async-profiler/releases/tag/v4.4)
|
||||
|
||||
- Linux x64: [async-profiler-4.3-linux-x64.tar.gz](https://github.com/async-profiler/async-profiler/releases/download/v4.3/async-profiler-4.3-linux-x64.tar.gz)
|
||||
- Linux arm64: [async-profiler-4.3-linux-arm64.tar.gz](https://github.com/async-profiler/async-profiler/releases/download/v4.3/async-profiler-4.3-linux-arm64.tar.gz)
|
||||
- macOS arm64/x64: [async-profiler-4.3-macos.zip](https://github.com/async-profiler/async-profiler/releases/download/v4.3/async-profiler-4.3-macos.zip)
|
||||
- Profile converters: [jfr-converter.jar](https://github.com/async-profiler/async-profiler/releases/download/v4.3/jfr-converter.jar)
|
||||
- Linux x64: [async-profiler-4.4-linux-x64.tar.gz](https://github.com/async-profiler/async-profiler/releases/download/v4.4/async-profiler-4.4-linux-x64.tar.gz)
|
||||
- Linux arm64: [async-profiler-4.4-linux-arm64.tar.gz](https://github.com/async-profiler/async-profiler/releases/download/v4.4/async-profiler-4.4-linux-arm64.tar.gz)
|
||||
- macOS arm64/x64: [async-profiler-4.4-macos.zip](https://github.com/async-profiler/async-profiler/releases/download/v4.4/async-profiler-4.4-macos.zip)
|
||||
- Profile converters: [jfr-converter.jar](https://github.com/async-profiler/async-profiler/releases/download/v4.4/jfr-converter.jar)
|
||||
|
||||
### Nightly builds
|
||||
|
||||
|
||||
31
scripts/compare-binary-sizes.sh
Executable file
31
scripts/compare-binary-sizes.sh
Executable file
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
# Copyright The async-profiler authors
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
function list-archive() {
|
||||
case "${1}" in
|
||||
*.tar.gz) tar -tzvf "${1}" --wildcards '*/bin/*' '*/lib/*' | awk '$1 ~ /^-/ { print $NF, $3 }' ;;
|
||||
*.zip) zipinfo -l "${1}" '*/bin/*' '*/lib/*' | awk '$1 ~ /^-/ { print $NF, $4 }' ;;
|
||||
esac | cut -d/ -f2- | sort
|
||||
}
|
||||
|
||||
function main() {
|
||||
if [[ ${#} -ne 2 ]]; then
|
||||
printf 'Usage: compare-binary-sizes.sh <base-archive> <treatment-archive>\n' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
[[ ${1} =~ (linux-x64|linux-arm64|macos) ]]
|
||||
printf '### %s\n\n| File | Base (KiB) | Treatment (KiB) | Delta (KiB) | %% Change |\n| --- | ---: | ---: | ---: | ---: |\n' "${BASH_REMATCH[1]}"
|
||||
join -a1 -a2 -e0 -o '0,1.2,2.2' \
|
||||
<(list-archive "${1}") \
|
||||
<(list-archive "${2}") \
|
||||
| awk '{
|
||||
b = $2; t = $3; d = t - b; pct = b > 0 ? d * 100 / b : 0
|
||||
printf "| `%s` | %.2f | %.2f | %+.2f | %+.2f%% |\n", $1, b/1024, t/1024, d/1024, pct
|
||||
}'
|
||||
}
|
||||
|
||||
[[ "${BASH_SOURCE[0]}" == "${0}" ]] && main "$@"
|
||||
@@ -201,7 +201,7 @@ public class AsyncProfiler implements AsyncProfilerMXBean {
|
||||
@Override
|
||||
public String dumpCollapsed(Counter counter) {
|
||||
try {
|
||||
return execute0("collapsed," + counter.name().toLowerCase());
|
||||
return execute0("collapsed," + (counter == Counter.SAMPLES ? "samples" : "total"));
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
@@ -242,12 +242,13 @@ public class AsyncProfiler implements AsyncProfilerMXBean {
|
||||
* <p>
|
||||
* This API is UNSTABLE and might change or be removed in the next version of async-profiler.
|
||||
*
|
||||
* @param counter Which counter to use for aggregation
|
||||
* @return OTLP representation of the profile
|
||||
*/
|
||||
@Override
|
||||
public byte[] dumpOtlp() {
|
||||
public byte[] dumpOtlp(Counter counter) {
|
||||
try {
|
||||
return execute1("otlp");
|
||||
return execute1("otlp," + (counter == Counter.SAMPLES ? "samples" : "total"));
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
||||
@@ -31,5 +31,5 @@ public interface AsyncProfilerMXBean {
|
||||
String dumpCollapsed(Counter counter);
|
||||
String dumpTraces(int maxTraces);
|
||||
String dumpFlat(int maxMethods);
|
||||
byte[] dumpOtlp();
|
||||
byte[] dumpOtlp(Counter counter);
|
||||
}
|
||||
|
||||
@@ -442,7 +442,9 @@ void VMStructs::resolveOffsets() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_klass_offset_addr != NULL) {
|
||||
JVMFlag* cjc = JVMFlag::find("CheckJNICalls");
|
||||
if (cjc != NULL && !cjc->get() && _klass_offset_addr != NULL) {
|
||||
// Create a synthetic fieldID to access VMKlass from jclass instance
|
||||
_klass = (jfieldID)(uintptr_t)(*_klass_offset_addr << 2 | 2);
|
||||
}
|
||||
|
||||
@@ -461,8 +463,7 @@ void VMStructs::resolveOffsets() {
|
||||
&& (_compact_object_headers ? (_markword_klass_shift >= 0 && _markword_monitor_value == MONITOR_BIT)
|
||||
: _oop_klass_offset >= 0)
|
||||
&& (_symbol_length_offset >= 0 || _symbol_length_and_refcount_offset >= 0)
|
||||
&& _symbol_body_offset >= 0
|
||||
&& _klass != NULL;
|
||||
&& _symbol_body_offset >= 0;
|
||||
|
||||
_has_method_structs = _jmethod_ids_offset >= 0
|
||||
&& _nmethod_method_offset >= 0
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
package test.api;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import one.profiler.AsyncProfiler;
|
||||
import one.profiler.Counter;
|
||||
import one.profiler.Events;
|
||||
@@ -22,7 +21,7 @@ public class DumpOtlp extends BusyLoops {
|
||||
}
|
||||
|
||||
// TODO: Should we test this further?
|
||||
byte[] profile = AsyncProfiler.getInstance().dumpOtlp();
|
||||
byte[] profile = AsyncProfiler.getInstance().dumpOtlp(Counter.TOTAL);
|
||||
System.out.println(profile.length);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
package test.otlp;
|
||||
|
||||
import one.profiler.AsyncProfiler;
|
||||
import one.profiler.Counter;
|
||||
import one.profiler.Events;
|
||||
import io.opentelemetry.proto.profiles.v1development.*;
|
||||
|
||||
@@ -39,7 +40,7 @@ public class OtlpProfileTimeTest {
|
||||
}
|
||||
|
||||
public static Profile dumpAndGetProfile(AsyncProfiler profiler) throws Exception {
|
||||
byte[] dump = profiler.dumpOtlp();
|
||||
byte[] dump = profiler.dumpOtlp(Counter.SAMPLES);
|
||||
ProfilesData data = ProfilesData.parseFrom(dump);
|
||||
return data.getResourceProfiles(0).getScopeProfiles(0).getProfiles(0);
|
||||
}
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
|
||||
package test.vmstructs;
|
||||
|
||||
import one.profiler.test.Assert;
|
||||
import one.profiler.test.Output;
|
||||
import one.profiler.test.Test;
|
||||
import one.profiler.test.TestProcess;
|
||||
import test.alloc.Hello;
|
||||
import test.smoke.Alloc;
|
||||
|
||||
public class VmstructsTests {
|
||||
@@ -25,4 +27,10 @@ public class VmstructsTests {
|
||||
Output out = p.profile("stop -o collapsed");
|
||||
assert out.contains("Alloc.allocate");
|
||||
}
|
||||
|
||||
@Test(mainClass = Hello.class, jvmArgs = "-Xcheck:jni", agentArgs = "start,event=alloc", output = true)
|
||||
public void checkJni(TestProcess p) throws Exception {
|
||||
p.waitForExit();
|
||||
Assert.isEqual(p.exitCode(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user