This repo stores benchmarks for the project using LLM.
It only tests a function 'sizeof' in C language. To show the result, you can directly run the 'main' void in 'simple test/src/sizeofTest.java'. The expected result is, ignoring warning messages, it prints 'Size of MyObject instance: 32 bytes' twice. Actually, it calculates the size of a struct defined in both sizeOfTest.java and sizeof.c, in two different ways, one is using Unsafe as another is using FFM api.
The original version is at https://github.com/well-grounded-java/resources. It contains two versions of a simple project about a bank account, the unsafe version and the ffm version. The Account.java
is an interface, and there are three kinds of accounts. Note that there are Junit tests for each type of accounts. The unsafe version allocate memory for the variable balance
, while the FFM version allocate off-heap memory to do the same thing. Tests for atomic and synchronized accounts all work well, as tests for var handled accounts sometimes fail, for both FFM version and unsafe version. Hence the failure occurs due to the unsafe version itself but not the way I modify it.
The original version is at https://github.com/HagarMeir/transactionLib. In Index.java
, it uses Unsafe to 1) allocate memory for a variable headOffset
, which indicates the offset of the field named head; 2) compare and swap objects atomically using UNSAFE.compareAndSwapObject
. The first usage is easy to transform, because FFM api can also allocate memory for a int variable. However, the headOffset
is used to get the value at the position &object+headOffset
, which is hard to do in Java. It's a thick that in this project, where &object+headOffset
is actually object.head
, which can be extracted using AtomicReferenceFieldUpdater
. To be honest, I first tried to ignore such transparent exposure, and pass the object type parameters to a library generated by a C program with FFM api. But I failed to do so, as I couldn't find a way to define a memory segment to allocate memory for this object, knowing neither the memory layout or the address of the object. Then I tried to pass the attributes in the object to the compareAndSwapObject
(short for cas
below) function, but there are too many attributes and I was confused should I really have to do it. Althrough I didn't choose to do it, I have to say it is the closest way to do automatically transform in my thought. I also tried to overload object.toStirng()
so that I can pass a string instead of an object. I worked a lot to overload them and write construct functions using a string, and there were many clues in my commit indicated how I tried. However, when I rewrote the cas
function, I realised that there was a easier way, which was the newest commit. I could use AtomicReferenceFieldUpdater
to compare and swap easier. Fortunately, all tests are passed. What's more, it's important that my method to transform this project is not extensible to other projects, at least not for automatic transformation. Because what I do is based on my comprehension of the project, doing some compulsory polishment, and my transformation doesn't use FFM api at all. To run this project, please make sure that the target bytecode version in Settings/Java Complier and the Java version in Run Configurations are both 22.
Based on JEP 471 (https://openjdk.org/jeps/471), I use MemorySegment and VarHandle to rewrite most of functions in sun.misc.Unsafe
. I make some Junit tests for it, and it can pass all of them.
Based on JEP 471 (https://openjdk.org/jeps/471), I use the three examples to build Junit tests, and it can pass all of them.
The original version is at https://github.com/EsotericSoftware/kryo. Use mvn clean && mvn install
to build it. It will past about 300 tests. The performance tests are shown in their repo readme file. For input, it use Input.java
, ByteBufferInput.java
, UnsafeInput.java
, and UnsafeByteBufferInput.java
, to do the same thing. Output is similar.
The origianl version is at https://github.com/google/gson. I only modify UnsafeAllocator.java
and delete some tests based on it. Use mvn clean verify
to test it.
The repo is https://github.com/jankotek/mapdb. The Unsafe version is from commit 4340d75, as the ByteBuffer version is from commit be0e111. mvn test
is ok for Unsafe version but not available for the ByteBuffer version due to Java version issues, although I think the ButeBuffer version is also right.
As shown in https://github.com/netty/netty/blob/065bfc40e74441cef387af83dfc5326468023f6d/common/src/main/java/io/netty/util/internal/CleanerJava6.java#L72, it writes two versions of code to do the same thing.
The original version is Bazel Release 7.3.0 (2024-08-12). Use env EXTRA_BAZEL_ARGS="--tool_java_runtime_version=22" bash ./compile.sh
to build it. Note that some BUILD files are also edited.
The original version is questdb Release 8.1.0. Use mvn test
to test it.
The original version is javassist Release 3.30.2-GA. Use mvn test
to test it. As shown in Line 238 of DefineClassHelper.java
, it use three methods to load a class.
The original version is Xenophanes release. In the tlatools/org.lamport.tlatools
folder, use ant -f customBuild.xml info compile compile-test dist
to build, and then use ant -f customBuild.xml test
to test.
The original version is commit cec7386. As shown in https://github.com/HotswapProjects/HotswapAgent/blob/cec7386c04eb703a6f1b5747a23a5ad6e011d455/hotswap-agent-core/src/main/java/org/hotswap/agent/javassist/util/proxy/DefineClassHelper.java#L241, it use three methods to load a class.
The original version is Release 1.5.0. It uses a variable USE_SUN_MISC_UNSAFE
to control the method to load a class. In protostuff/protostuff-runtime/src/main/java/io/protostuff/runtime/RuntimeFieldFactory.java
Line 173, the static block uses either Unsafe or Reflection to do the same thing.
The original version is Release 0.11.4. Use gradle clean && gradle test
to test it. Note that both the original version and the modified version will pass 194/207 tests.
The original version is Release 3.0.0. Use mvn clean && mvn test
to test it. It will pass 178 tests.
The original version is Release 0.6.0. In Procyon.Reflection/src/main/java/com/strobel/reflection/emit/TypeBuilder.java
, it uses two methods to define a class in the bottom of the code.
The original version is Release 2.37.0. In artemis-commons/src/main/java/org/apache/activemq/artemis/utils/UTF8Util.java
, it uses three methods to perform writeUTF
.
The original version is Release 6.1.1. In cdap-api-common/src/main/java/io/cdap/cdap/api/common/Bytes.java
, it uses several methods to perform compareTo
.
The original version is Release 1.10.8. In src/main/java/org/joml/Matrix3f.java
, it uses either ByteBuffer
or Unsafe
to perform matrix operations. The unsafe codes can be replaced with VarHandle. Use gradle clean && gradle test
to test it.
The formal report which contains performance tests can be referred to https://www.overleaf.com/read/fdxffczpmymt#d0f01c. Note that in the first verson of atomic operation test, I found an interesting result which showed the performance order that Unsafe < Unsafe&CheckBounds < FFM:
However, after I modifed the output style to tables, I couldn't get the same result. The reason is still not clear.