Skip to content

Commit 1212361

Browse files
committed
Add support for 4.0, drop support for older releases #23
1 parent c82c6a5 commit 1212361

File tree

9 files changed

+179
-172
lines changed

9 files changed

+179
-172
lines changed

README.md

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ Loader for AsyncProfiler
44
[![Maven Central](https://img.shields.io/maven-central/v/me.bechberger/ap-loader-all)](https://search.maven.org/search?q=ap-loader) [![GitHub](https://img.shields.io/github/license/jvm-profiling-tools/ap-loader)](https://github.com/jvm-profiling-tools/ap-loader/blob/main/LICENSE)
55

66
Packages [async-profiler](https://github.com/jvm-profiling-tools/async-profiler) releases in a JAR
7-
with an `AsyncProfilerLoader` (version 4.*, 3.*, 2.* and 1.8.*)
7+
with an `AsyncProfilerLoader` (version 4.*, old releases up to -9 support 3.*, 2.* and 1.8.*)
88
that loads the suitable native library for the current platform.
99

10-
*In >= 3.* it also includes the latest [jattach](https://github.com/apangin/jattach) binary. This was previously
11-
part of async-profiler.*
10+
It includes the latest [jattach](https://github.com/apangin/jattach) binary. This was previously
11+
part of async-profiler.
1212

1313
This is usable as a Java agent (same arguments as the async-profiler agent) and as the basis for other libraries.
1414
The real rationale behind this library is that the async-profiler is a nice tool, but it cannot be easily integrated
@@ -50,11 +50,11 @@ from maven central, e.g:
5050
<dependency>
5151
<groupId>me.bechberger</groupId>
5252
<artifactId>ap-loader-all</artifactId>
53-
<version>4.0-9</version>
53+
<version>4.0-10</version>
5454
</dependency>
5555
```
5656

57-
Others are of course available, see [maven central](https://central.sonatype.com/artifact/me.bechberger/ap-loader-all/4.0-9).
57+
Others are of course available, see [maven central](https://central.sonatype.com/artifact/me.bechberger/ap-loader-all/4.0-10).
5858

5959
You can also use [JBang](https://jbang.dev) to simplify the usage of ap-loader. There are examples in documentation below.
6060

@@ -68,7 +68,7 @@ Variants
6868
--------
6969
The JAR can be obtained in the following variants:
7070

71-
- `macos`, `linux-x64`, ...: `jattach`, `profiler.sh`/`asprof` and `libasyncProfiler.so` for the given platform
71+
- `macos`, `linux-x64`, ...: `jattach`, `asprof`, `jfrconv` and `libasyncProfiler.so` for the given platform
7272
- `all`: all of the above
7373

7474
Regarding file sizes: The `all` variant are` `typically around 800KB and the individual variants around 200 to 400KB.
@@ -99,7 +99,7 @@ Usage: java -jar ap-loader.jar <command> [args]
9999
Commands:
100100
help show this help
101101
jattach run the included jattach binary
102-
profiler run the included profiler.sh/asprof script
102+
profiler run the included asprof script
103103
agentpath prints the path of the extracted async-profiler agent
104104
jattachpath prints the path of the extracted jattach binary
105105
supported fails if this JAR does not include a profiler for the current OS and architecture
@@ -128,7 +128,7 @@ See the [GitHub page of jattach](https://github.com/apangin/jattach) for more de
128128
129129
### profiler
130130
131-
`java -jar ap-loader.jar profiler` is equivalent to calling the suitable `profiler.sh`/`asprof`:
131+
`java -jar ap-loader.jar profiler` is equivalent to calling the suitable `asprof`:
132132
133133
```sh
134134
# Profile a process for `n` seconds
@@ -234,7 +234,7 @@ The latest `all` version can be added via:
234234
<dependency>
235235
<groupId>me.bechberger</groupId>
236236
<artifactId>ap-loader-all</artifactId>
237-
<version>4.0-9</version>
237+
<version>4.0-10</version>
238238
</dependency>
239239
```
240240
@@ -253,11 +253,11 @@ python3 ./bin/releaser.py download 4.0
253253
# build the JAR for the release
254254
# maven might throw warnings, related to the project version setting,
255255
# but the alternative solutions don't work, so we ignore the warning for now
256-
mvn -Dproject.vversion=4.0 -Dproject.subrelease=9 -Dproject.platform=macos package assembly:single
256+
mvn -Dproject.vversion=4.0 -Dproject.subrelease=10 -Dproject.platform=macos package assembly:single
257257
# use it
258-
java -jar target/ap-loader-macos-4.0-9-full.jar ...
258+
java -jar target/ap-loader-macos-4.0-10-full.jar ...
259259
# build the all JAR
260-
mvn -Dproject.vversion=4.0 -Dproject.subrelease=9 -Dproject.platform=all package assembly:single
260+
mvn -Dproject.vversion=4.0 -Dproject.subrelease=10 -Dproject.platform=all package assembly:single
261261
```
262262
263263
Development
@@ -302,6 +302,13 @@ And the following for a new async-profiler release:
302302
Changelog
303303
---------
304304
305+
### v10
306+
307+
- Drop support for async-profiler < 4.0 versions, as 4.0 changed how its tested
308+
- Major changes in the usage of the JFR conversion made by async-profiler
309+
which are not hidden
310+
- Clean up the code
311+
305312
### v9
306313
307314
- Fix FlameGraph converter [#22](https://github.com/jvm-profiling-tools/ap-loader/issues/22)

bin/copy_libs.sh

Lines changed: 23 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -18,58 +18,33 @@ if [ -z "$3" ]; then
1818
fi
1919
mkdir -p target/classes/libs
2020

21-
# if version is smaller than 2.10:
22-
if ([ "$major_version" -le 2 ] && [ "$minor_version" -lt 10 ]); then
23-
echo "Copy $AP_RELEASE/build/libasyncProfiler.so"
24-
cp "$AP_RELEASE/build/libasyncProfiler.so" \
25-
"target/classes/libs/libasyncProfiler-$VERSION_PLATFORM.so"
26-
cp "$AP_RELEASE/build/jattach" \
27-
"target/classes/libs/jattach-$VERSION_PLATFORM"
21+
# test endings ".so" and ".dylib" in a loop
22+
for ending in "so" "dylib"; do
23+
# if the file exists, copy it
24+
if [ -f "$AP_RELEASE/lib/libasyncProfiler.$ending" ]; then
25+
echo "Copy $AP_RELEASE/lib/libasyncProfiler.$ending"
26+
cp "$AP_RELEASE/lib/libasyncProfiler.$ending" \
27+
"target/classes/libs/libasyncProfiler-$VERSION_PLATFORM.$ending"
28+
echo "libasyncProfiler-$VERSION_PLATFORM.$ending" > target/classes/libs/ap-profile-lib-$VERSION_PLATFORM
29+
fi
30+
done
2831

29-
cp "$AP_RELEASE/build/libasyncProfiler.so" \
30-
"target/classes/libs/libasyncProfiler-$VERSION_PLATFORM.so"
32+
cp "$AP_RELEASE/build/jattach" \
33+
"target/classes/libs/jattach-$VERSION_PLATFORM"
3134

32-
echo "libasyncProfiler-$VERSION_PLATFORM.so" > target/classes/libs/ap-profile-lib-$VERSION_PLATFORM
35+
cp "$AP_RELEASE/build/jattach" \
36+
"target/classes/libs/jattach-$VERSION_PLATFORM"
3337

34-
cp "$AP_RELEASE/build/jattach" \
35-
"target/classes/libs/jattach-$VERSION_PLATFORM"
38+
cp "$AP_RELEASE/bin/jfrconv" \
39+
"target/classes/libs/jfrconv-$VERSION_PLATFORM"
3640

37-
python3 "$OWN_DIR/timestamp.py" > "target/classes/libs/ap-timestamp-$version"
38-
echo "$version" > target/classes/libs/ap-version
41+
python3 "$OWN_DIR/timestamp.py" > "target/classes/libs/ap-timestamp-$version"
42+
echo "$version" > target/classes/libs/ap-version
3943

40-
echo "Copy $AP_RELEASE/profiler.sh"
41-
cp "$AP_RELEASE/profiler.sh" "target/classes/libs/profiler-$version.sh"
42-
python3 "$OWN_DIR/profile_processor.py" "target/classes/libs/profiler-$version.sh"
44+
echo "Copy $AP_RELEASE/bin/asprof"
45+
cp "$AP_RELEASE/bin/asprof" "target/classes/libs/asprof-$VERSION_PLATFORM"
4346

44-
echo "profiler-$version.sh" > target/classes/libs/ap-profile-script-$VERSION_PLATFORM
47+
echo "asprof-$VERSION_PLATFORM" > target/classes/libs/ap-profile-script-$VERSION_PLATFORM
4548

46-
echo "Copy Java sources"
47-
python3 "$OWN_DIR/copy_java_sources.py" "$BASEDIR" "$VERSION_PLATFORM"
48-
49-
else
50-
# test endings ".so" and ".dylib" in a loop
51-
for ending in "so" "dylib"; do
52-
# if the file exists, copy it
53-
if [ -f "$AP_RELEASE/lib/libasyncProfiler.$ending" ]; then
54-
echo "Copy $AP_RELEASE/lib/libasyncProfiler.$ending"
55-
cp "$AP_RELEASE/lib/libasyncProfiler.$ending" \
56-
"target/classes/libs/libasyncProfiler-$VERSION_PLATFORM.$ending"
57-
echo "libasyncProfiler-$VERSION_PLATFORM.$ending" > target/classes/libs/ap-profile-lib-$VERSION_PLATFORM
58-
fi
59-
done
60-
61-
cp "$AP_RELEASE/build/jattach" \
62-
"target/classes/libs/jattach-$VERSION_PLATFORM"
63-
64-
python3 "$OWN_DIR/timestamp.py" > "target/classes/libs/ap-timestamp-$version"
65-
echo "$version" > target/classes/libs/ap-version
66-
67-
echo "Copy $AP_RELEASE/bin/asprof"
68-
cp "$AP_RELEASE/bin/asprof" "target/classes/libs/asprof-$VERSION_PLATFORM"
69-
70-
echo "asprof-$VERSION_PLATFORM" > target/classes/libs/ap-profile-script-$VERSION_PLATFORM
71-
72-
echo "Copy Java sources"
73-
python3 "$OWN_DIR/copy_java_sources.py" "$BASEDIR" "$VERSION_PLATFORM"
74-
75-
fi
49+
echo "Copy Java sources"
50+
python3 "$OWN_DIR/copy_java_sources.py" "$BASEDIR" "$VERSION_PLATFORM"

bin/profile_processor.py

Lines changed: 0 additions & 13 deletions
This file was deleted.

bin/releaser.py

Lines changed: 53 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,16 @@
1515
import tempfile
1616
import time
1717
from enum import Enum
18+
from math import expm1
1819
from pathlib import Path
1920
from typing import Any, Dict, List, Union, Tuple, Optional
2021
from urllib import request
2122

22-
SUB_VERSION = 9
23-
RELEASE_NOTES = """- Fix FlameGraph converter [#22](https://github.com/jvm-profiling-tools/ap-loader/issues/22)
23+
SUB_VERSION = 10
24+
RELEASE_NOTES = """- Drop support for async-profiler < 4.0 versions, as 4.0 changed how its tested
25+
- Major changes in the usage of the JFR conversion made by async-profiler
26+
which are not hidden
27+
- Clean up the code
2428
"""
2529

2630
HELP = """
@@ -158,8 +162,11 @@ def get_release_versions(tool: Tool) -> List[str]:
158162

159163

160164
def get_most_recent_release(tool: Tool) -> str:
161-
return [version for version in get_release_versions(tool) if
162-
version.startswith("3.") or version.startswith("4.") or version.startswith("2.")][0]
165+
def check_version(version: str) -> bool:
166+
if tool == Tool.ASYNC_PROFILER:
167+
return version.startswith("4.")
168+
return version.startswith( "2.")
169+
return [version for version in get_release_versions(tool) if check_version(version)][0]
163170

164171

165172
def get_release_info(tool: Tool, release: str) -> str:
@@ -302,22 +309,35 @@ def build_tests(release: str):
302309
release_file = release_target_file(release, "all")
303310
shutil.copytree(code_folder, TESTS_CODE_DIR)
304311
test_folder = f"{TESTS_CODE_DIR}/test"
305-
for file in os.listdir(test_folder):
306-
if file.endswith(".java"):
307-
execute(f"javac {test_folder}/{file}")
308-
if file.endswith(".sh") and not file.startswith("fd"):
309-
with open(f"{test_folder}/{file}") as f:
310-
content = f.read()
311-
content = content.replace("../profiler.sh ",
312-
f"java -jar '{release_file}' profiler ").replace(
313-
"../build/bin/asprof",
314-
f"java -jar '{release_file}' profiler").replace(
315-
"-agentpath:../build/libasyncProfiler.so",
316-
f"-javaagent:{release_file}").replace(
317-
"-agentpath:$(ls ../build/lib/libasyncProfiler.*)",
318-
f"-javaagent:{release_file}")
319-
with open(f"{test_folder}/{file}", "w") as f:
320-
f.write(content)
312+
# walk all files in the folder recursively and replace the paths
313+
# to the release file
314+
for root, dirs, files in os.walk(TESTS_CODE_DIR):
315+
for file in files:
316+
if file.endswith(".java") or file.endswith("Makefile"):
317+
with open(f"{root}/{file}") as f:
318+
content = f.read()
319+
content = (content
320+
.replace("-source 7 -target 7", "-source 8 -target 8")
321+
.replace('cmd.add("-agentpath:" + profilerLibPath() + "=" +',
322+
f'cmd.add("-javaagent:{release_file}" + "=" +')
323+
.replace(
324+
'cmd.add("build/bin/asprof")',
325+
f'cmd.addAll(List.of("java", "-jar", "{release_file}", "profiler"))'))
326+
if file == "AllocTests.java":
327+
# the startup test doesn't work
328+
# so let's find the @Test annotation in the line before
329+
# 'public void startup(TestProcess p)' and remove it
330+
lines = content.splitlines()
331+
# find startup line
332+
startup_line = next(i for i, line in enumerate(lines) if
333+
"public void startup(TestProcess p)" in line)
334+
# find the line before
335+
before_startup_line = startup_line - 1
336+
# find the @Test annotation
337+
lines = lines[:before_startup_line] + lines[startup_line:]
338+
content = "\n".join(lines)
339+
with open(f"{root}/{file}", "w") as f:
340+
f.write(content)
321341

322342

323343
def clear_tests_dir():
@@ -331,6 +351,7 @@ def test_release_basic_execution(release: str, platform: str,
331351
Tests that the agentpath command returns a usable agent on this platform
332352
"""
333353
release_file = release_target_file(release, platform)
354+
cmd = ""
334355
try:
335356
pipe = subprocess.PIPE if not ignore_output else subprocess.DEVNULL
336357
clear_tests_dir()
@@ -345,23 +366,26 @@ def test_release_basic_execution(release: str, platform: str,
345366
return False
346367
profile_file = f"{TESTS_DIR}/profile.jfr"
347368
cmd = f"java -javaagent:{release_file}=start,file={profile_file},jfr " \
348-
f"-cp {TESTS_CODE_DIR}/test ThreadsTarget"
369+
f"{CURRENT_DIR}/misc/TestMain.java"
349370
if not ignore_output:
350-
print(f"Execute {cmd}")
371+
print(f"Execute cd {CURRENT_DIR}; {cmd}")
351372
subprocess.check_call(cmd, shell=True, cwd=CURRENT_DIR, stdout=pipe,
352373
stderr=pipe)
353374
if not os.path.exists(profile_file):
354375
return False
355376
flamegraph_file = f"{TESTS_DIR}/flamegraph.html"
356-
cmd = f"java -jar '{release_file}' converter jfr2flame {profile_file} {flamegraph_file}"
377+
cmd = f"java -jar '{release_file}' converter -o html {profile_file} {flamegraph_file}"
357378
if not ignore_output:
358-
print(f"Execute {cmd}")
379+
print(f"Execute cd {CURRENT_DIR}; {cmd}")
359380
subprocess.check_call(cmd, shell=True, cwd=CURRENT_DIR, stdout=pipe,
360381
stderr=pipe)
361382
if not os.path.exists(flamegraph_file):
383+
print("no flamegraph file")
362384
return False
363385
return True
364386
except subprocess.CalledProcessError:
387+
if not ignore_output:
388+
print(f"Error executing command: {cmd}")
365389
return False
366390

367391

@@ -400,14 +424,10 @@ def run_async_profiler_test(test_script: str) -> bool:
400424

401425
def run_async_profiler_tests():
402426
print("Run async-profiler tests")
403-
test_folder = f"{TESTS_CODE_DIR}/test"
404-
failed = False
405-
for file in os.listdir(test_folder):
406-
if file.endswith(".sh") and not file.startswith("fd"):
407-
if not run_async_profiler_test(file):
408-
failed = True
409-
if failed:
410-
raise Exception("Some async-profiler tests failed")
427+
try:
428+
subprocess.check_call("make test", cwd=TESTS_CODE_DIR, shell=True,)
429+
except subprocess.CalledProcessError as ex:
430+
raise Exception(f"Some async-profiler tests failed {ex}")
411431

412432

413433
def test_release(release: str):
@@ -529,8 +549,7 @@ def cli():
529549
coms = {"current_version": lambda: print(
530550
get_most_recent_release(Tool.ASYNC_PROFILER)),
531551
"versions": lambda: print(" ".join(
532-
version for version in get_release_versions(Tool.ASYNC_PROFILER) if
533-
version.startswith("2.") or version.startswith("3.") or version.startswith("4."))),
552+
version for version in get_release_versions(Tool.ASYNC_PROFILER) if version.startswith("4."))),
534553
"download": lambda: download_release(release),
535554
"build": lambda: build_release(release),
536555
"test": lambda: test_release(release),

jbang-catalog.json

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,11 @@
55
"script-ref": "https://github.com/jvm-profiling-tools/ap-loader/releases/latest/download/ap-loader-all.jar",
66
"description": "async profiler loader. Use directly with `jbang ap-loader@jvm-profiling-tools/ap-loader` or use as agent with `jbang --javaagent\u003dap-loader@jvm-profile-tools/ap-loader ...`."
77
},
8-
"jfr2nflx": {
9-
"script-ref": "https://github.com/jvm-profiling-tools/ap-loader/releases/latest/download/ap-loader-all.jar",
10-
"main": "one.converter.jfr2nflx",
11-
"java-agents": []
12-
},
13-
"jfr2pprof": {
14-
"script-ref": "https://github.com/jvm-profiling-tools/ap-loader/releases/latest/download/ap-loader-all.jar",
15-
"main": "one.converter.jfr2pprof",
16-
"java-agents": []
17-
},
18-
"jfr2flame": {
19-
"script-ref": "https://github.com/jvm-profiling-tools/ap-loader/releases/latest/download/ap-loader-all.jar",
20-
"main": "one.converter.jfr2flame",
21-
"java-agents": []
22-
},
238
"converter": {
249
"script-ref": "https://github.com/jvm-profiling-tools/ap-loader/releases/latest/download/ap-loader-all.jar",
25-
"main": "one.converter.Main",
10+
"arguments": [
11+
"converter"
12+
],
2613
"java-agents": []
2714
},
2815
"profiler": {

misc/TestMain.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// a main class that just waste some cpu for two seconds
2+
3+
public class TestMain {
4+
public static void main(String[] args) throws Exception {
5+
long start = System.currentTimeMillis();
6+
int i = 0;
7+
while (System.currentTimeMillis() - start < 2000) {
8+
i = Math.pow(i + 1, 2) > 1000000 ? 0 : i + 1;
9+
}
10+
}
11+
}

0 commit comments

Comments
 (0)