Skip to content

Commit

Permalink
Use JOL to determine AllocObject overhead and minimum size (#80)
Browse files Browse the repository at this point in the history
* Use JOL to compute size of AllocObject and enforce this as minimum object size

* Include array overhead in total
  • Loading branch information
earthling-amzn authored Dec 12, 2024
1 parent 4c7e556 commit 79e5ebf
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 79 deletions.
47 changes: 32 additions & 15 deletions HyperAlloc/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,19 @@
<artifactId>mockito-core</artifactId>
<version>3.3.3</version>
</dependency>
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.17</version>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
Expand Down Expand Up @@ -383,21 +392,29 @@
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>false</addClasspath>
<mainClass>com.amazon.corretto.benchmark.hyperalloc.HyperAlloc</mainClass>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
<manifestEntries>
<Premain-Class>com.amazon.corretto.benchmark.hyperalloc.HyperAlloc</Premain-Class>
<Agent-Class>com.amazon.corretto.benchmark.hyperalloc.HyperAlloc</Agent-Class>
</manifestEntries>
</archive>
</configuration>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<id>hyper-alloc</id>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>HyperAlloc</finalName>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Premain-Class>org.openjdk.jol.vm.InstrumentationSupport</Premain-Class>
<Launcher-Agent-Class>org.openjdk.jol.vm.InstrumentationSupport$Installer</Launcher-Agent-Class>
</manifestEntries>
<mainClass>com.amazon.corretto.benchmark.hyperalloc.HyperAlloc</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
// SPDX-License-Identifier: Apache-2.0
package com.amazon.corretto.benchmark.hyperalloc;

import org.openjdk.jol.info.ClassLayout;
import org.openjdk.jol.info.GraphLayout;

import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.LongAdder;

Expand All @@ -10,24 +13,19 @@
* to another AllocObject to allow us creating a complex reachability graph among them.
*/
class AllocObject {
private static ObjectOverhead objectOverhead = ObjectOverhead.CompressedOops;

private static final ObjectOverhead objectOverhead = new ObjectOverhead();
private static final LongAdder BytesAllocated = new LongAdder();

/**
* Set the object overhead. By default it assumes that compressedOops is enabled.
* @param overhead Object size overhead in heap.
*/
static void setOverhead(final ObjectOverhead overhead) {
objectOverhead = overhead;
}

private AllocObject next;
private byte[] data;
private final byte[] data;

AllocObject(final int size) {
this.data = new byte[size];
this.next = null;
}

AllocObject(final int size, final AllocObject ref) {
assert size >= objectOverhead.getOverhead()
: "The object size cannot be smaller than the overhead(" + objectOverhead + ").";
this.data = new byte[size - objectOverhead.getOverhead()];
this.next = ref;
}
Expand Down Expand Up @@ -96,6 +94,8 @@ static AllocObject create(final int size) {
}

static AllocObject create(final int size, final AllocObject ref) {
assert size >= objectOverhead.getOverhead()
: "The object size cannot be smaller than the overhead(" + objectOverhead + ").";
BytesAllocated.add(size);
return new AllocObject(size, ref);
}
Expand All @@ -104,24 +104,15 @@ static long getBytesAllocated() {
return BytesAllocated.longValue();
}

static int getObjectOverhead() {
return objectOverhead.overhead;
}

/**
* The enumeration to AllocObject overhead in heap.
*/
enum ObjectOverhead {
/// AllocObject: | header (12) | ref to next (4) | ref to array (4) | align (4) |
/// Byte array: | header (12) | length (4) |
CompressedOops(40),

/// AllocObject: | header (16) | ref to next (8) | ref to array (8) |
/// Byte array: | header (16) | length (4) | align (4) |
NonCompressedOops(56);

private int overhead;

ObjectOverhead(final int overhead) {
this.overhead = overhead;
}

static class ObjectOverhead {
private final int overhead = (int) GraphLayout.parseInstance(new AllocObject(0)).totalSize();
int getOverhead() {
return overhead;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,3 @@ public static void main(String[] args) {
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,13 @@ public SimpleRunConfig(final String[] args) {
} else if (args[i].equals("-t")) {
numOfThreads = Integer.parseInt(args[++i]);
} else if (args[i].equals("-n")) {
minObjectSize = Integer.parseInt(args[++i]);
int requestedMinObjectSize = Integer.parseInt(args[++i]);
if (requestedMinObjectSize < AllocObject.getObjectOverhead()) {
System.out.println("Minimum object size includes the object header, minimum object size is: " + AllocObject.getObjectOverhead());
minObjectSize = AllocObject.getObjectOverhead();
} else {
minObjectSize = requestedMinObjectSize;
}
} else if (args[i].equals("-x")) {
maxObjectSize = Integer.parseInt(args[++i]);
} else if (args[i].equals("-r")) {
Expand Down Expand Up @@ -119,7 +125,7 @@ public SimpleRunConfig(final long allocRateInMbPerSecond, final double allocSmoo
this.midAgedInMb = midAgedInMb;
this.durationInSecond = durationInSecond;
this.numOfThreads = numOfThreads;
this.minObjectSize = minObjectSize;
this.minObjectSize = Math.max(minObjectSize, AllocObject.getObjectOverhead());
this.maxObjectSize = maxObjectSize;
this.pruneRatio = pruneRatio;
this.reshuffleRatio = reshuffleRatio;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ public SimpleRunner(SimpleRunConfig config) {
public void start() {
System.out.println("Starting a SimpleRunner");
try {
AllocObject.setOverhead(config.isUseCompressedOops() ? AllocObject.ObjectOverhead.CompressedOops
: AllocObject.ObjectOverhead.NonCompressedOops);
final ObjectStore store = new ObjectStore(config.getLongLivedInMb(), config.getPruneRatio(),
config.getReshuffleRatio());
final Thread storeThread = new Thread(store);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,36 +78,4 @@ void ObjectCreateFixedTest() {
assertThat(size, lessThan(i + 8));
}
}

@Test
void OverheadTest() {
AllocObject.setOverhead(AllocObject.ObjectOverhead.CompressedOops);
assertDoesNotThrow(() -> AllocObject.create(40, 40, null));
AllocObject.setOverhead(AllocObject.ObjectOverhead.NonCompressedOops);
assertThrows(AssertionError.class, () -> AllocObject.create(40, 40, null));
assertDoesNotThrow(() -> AllocObject.create(56, 56, null));

AllocObject.setOverhead(AllocObject.ObjectOverhead.CompressedOops);
}

@Test
@Disabled("Only run when compressed oops disabled.")
void ObjectSizeNoCompressedOopsTest() {
AllocObject.setOverhead(AllocObject.ObjectOverhead.NonCompressedOops);

final AllocObject o1 = new AllocObject(56, null);
final AllocObject o2 = new AllocObject(57, null);
final AllocObject o3 = new AllocObject(58, null);
final AllocObject o4 = new AllocObject(59, null);
final AllocObject o5 = new AllocObject(65, null);

final AllocObject o6 = new AllocObject(1024, null);

assertThat(o1.getRealSize(), is(56));
assertThat(o2.getRealSize(), is(64));
assertThat(o3.getRealSize(), is(64));
assertThat(o4.getRealSize(), is(64));
assertThat(o5.getRealSize(), is(72));
assertThat(o6.getRealSize(), is(1024));
}
}

0 comments on commit 79e5ebf

Please sign in to comment.