Simple Java Sampling Wrapper (SJSW) is a async-profiler Java wrapper library that attaches
async-profiler
to external Java process as an agent.
SJSW currently can:
- Launch Java process with async-profiler attached as a Java agent.
- Write raw async-profiler results to a file.
- Read such results, and convert them into stack call tree.
This project is part of my bachelor's thesis Examination of Performance Change Detection Efficiency Using Sampling and Instrumentation Techniques
(2024-2025).
Regardless in what mode (standalone or integrated as a lib) you plan to use SJSW, you need to adjust the configuration.
Configuration file looks like this:
{
"classPath": "/path/.../exampleProject/target/classes",
"mainClass": "com.example.benchmark.Benchmark",
"profilerPath": "/home/test/tmp/async-profiler/build/lib/libasyncProfiler.so",
"outputPath": "/home/test/output.sampler.json",
"profilerRawOutputPath": "/home/test/asprof.sjsw.output.raw.json"
}
Be advised, that the configuration file can be overridden by Java arguments if they are supplied in the same order as they are in the config.json
.
classPath
: folder where compiled Java classes of the benchmark application reside, or a location of a text file (*.txt) with all classpaths.
mainClass
: main class coordinates of the benchmark application
profilerPath
: path to the async-profiler executable file. If you're using Linux or MacOS, you can use ones already included in this project:
async-profiler executables for Linux and MacOS are included in this project:
For linux: ./executables/linux/lib/libasyncProfiler.so
For MacOS: ./executables/macos/lib/libasyncProfiler.so
outputPath
: output path of internal SJSW structure. In the next release, this will be changed to the serialized output of the call stack tree.
profilerRawOutputPath
: raw output path of async-profiler.
If you want to use SJSW in you own project:
- Create a new executor instance:
private static final SamplerExecutorPipeline executor = new AsyncProfilerExecutor();
- Retrieve configuration
Config CONFIGURATION = Config.retrieveConfiguration(new File("config.json")); // OR Config CONFIGURATION = Config.retrieveConfiguration(args);
- Call
execute
method to start Java application with async-profiler attached, and executewrite
method afterward to record results to a file.executor.execute(CONFIGURATION, Duration.ofSeconds(8)); executor.write(CONFIGURATION.outputPath());
-
Make sure you use SJSW with JDK17.
-
In config.json adjust
profilerPath
value to either your local path oflibasyncProfiler.so
, or to relative path of already included async-profiler executables (see Configuration File) -
Execute to allow event access for unprivileged users (non sudo users)
sudo sysctl kernel.perf_event_paranoid=1
-
Adjust values remaining values in config.json like described in Configuration File section that are specific to your benchmark project.
-
Execute StandaloneSampler as main, or use the SamplerExecutorPipeline like it is described in Using as a Library
-
Raw output and the tree should be outputted to the console.