Skip to content

Commit

Permalink
Make the logging of the memory layout at startup optional
Browse files Browse the repository at this point in the history
patch by Benjamin Lerer; reviewed by ekaterina Dimitrova for JAMM-58
  • Loading branch information
blerer committed Jul 18, 2023
1 parent 453ffda commit 867d781
Show file tree
Hide file tree
Showing 10 changed files with 64 additions and 13 deletions.
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,17 @@ Moreover as specified in the `Supported Java versions` section the `ContendedPad

## Debugging

### Layout and JVM information

The `org.github.jamm.strategies.LogInfoAtStartup` system property can be set to `true` to request Jamm to log at startup in `System.out` information about the JVM and the detected memory layout.

Example of output:

```
Jamm starting with: java.version='1.8.0_144', java.vendor='Oracle Corporation', instrumentation=true, unsafe=true, Memory Layout: [objectHeaderSize=12 , arrayHeaderSize=16, objectAlignment=8, referenceSize=4, contendedPaddingWidth=128]
```
### Visited object tree

In order to see the object tree visited when calling `MemoryMeter.measureDeep` and ensuring that it matches your
expectations you can build the `MemoryMeter` instance using `printVisitedTree`:

Expand Down
6 changes: 3 additions & 3 deletions src/org/github/jamm/MemoryMeter.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public static boolean hasUnsafe() {
}

public static boolean useStringOptimization() {
return StringMeter.ENABLE;
return StringMeter.ENABLED;
}

/**
Expand Down Expand Up @@ -418,7 +418,7 @@ public long measureArray(long[] array) {
*/
public long measureStringDeep(String s) {

if (StringMeter.ENABLE) {
if (StringMeter.ENABLED) {

if (s == null)
return 0L;
Expand Down Expand Up @@ -471,7 +471,7 @@ public long measureDeep(Object object, ByteBufferMode bbMode) {
Object current = stack.pop();

// Deal with optimizations first.
if (StringMeter.ENABLE && current instanceof String) {
if (StringMeter.ENABLED && current instanceof String) {
String s = (String) current;
long size1 = measureDeep(s, listener);
total += size1;
Expand Down
21 changes: 16 additions & 5 deletions src/org/github/jamm/strategies/MemoryMeterStrategies.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,16 +79,27 @@ private static MemoryMeterStrategies createStrategies() {
MemoryMeterStrategy specStrategy = createSpecStrategy(mayBeIsHiddenMH);
MemoryMeterStrategy unsafeStrategy = createUnsafeStrategy(mayBeIsHiddenMH, (MemoryLayoutBasedStrategy) specStrategy);

if (logInformationAtStartup()) {
// Logging important information once at startup for debugging purpose
System.out.println("Jamm starting with: java.version='" + System.getProperty("java.version")
+ "', java.vendor='" + System.getProperty("java.vendor")
+ "', instrumentation=" + (instrumentationStrategy != null)
+ ", unsafe=" + (unsafeStrategy != null)
+ ", " + MemoryMeterStrategy.MEMORY_LAYOUT);
System.out.println("Jamm starting with: java.version='" + System.getProperty("java.version")
+ "', java.vendor='" + System.getProperty("java.vendor")
+ "', instrumentation=" + (instrumentationStrategy != null)
+ ", unsafe=" + (unsafeStrategy != null)
+ ", " + MemoryMeterStrategy.MEMORY_LAYOUT);
}

return new MemoryMeterStrategies(instrumentationStrategy, instrumentationAndSpecStrategy, unsafeStrategy, specStrategy);
}

/**
* Checks if layout and JDK information should be logged at startup.
* <p>{@code false} by default to avoid causing issues to existing applications that do not expect that message to be logged.</p>
* @return {@code true} if the information should be logged, {@code false} otherwise.
*/
private static boolean logInformationAtStartup() {
return Boolean.parseBoolean(System.getProperty("org.github.jamm.strategies.LogInfoAtStartup", "false"));
}

private static MemoryMeterStrategy createSpecStrategy(Optional<MethodHandle> mayBeIsHiddenMH) {

if (mayBeIsHiddenMH.isPresent() && !VM.useEmptySlotsInSuper())
Expand Down
2 changes: 1 addition & 1 deletion src/org/github/jamm/string/StringMeter.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public abstract class StringMeter {
/**
* Enable or disable string optimization through the {@code org.github.jamm.string.Optimize} String system property. {@code true} by default.
*/
public static final boolean ENABLE = Boolean.parseBoolean(System.getProperty("org.github.jamm.string.Optimize", "true"));
public static final boolean ENABLED = Boolean.parseBoolean(System.getProperty("org.github.jamm.string.Optimize", "true"));

/**
* The String shallow size stored as a constant to have it compiled directly into the measure method.
Expand Down
5 changes: 5 additions & 0 deletions test/org/github/jamm/GuessTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@
@RunWith(Parameterized.class)
public class GuessTest {

@BeforeClass
public static void logInfoAtStartup() {
System.setProperty("org.github.jamm.strategies.LogInfoAtStartup", "true");
}

@Parameterized.Parameters
public static Collection<MemoryMeter.Guess> guesses() {

Expand Down
10 changes: 8 additions & 2 deletions test/org/github/jamm/MemoryMeterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.function.Predicate;

import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
Expand All @@ -17,8 +18,13 @@
import static org.junit.Assert.assertNotEquals;

@RunWith(Parameterized.class)
public class MemoryMeterTest
{
public class MemoryMeterTest {

@BeforeClass
public static void logInfoAtStartup() {
System.setProperty("org.github.jamm.strategies.LogInfoAtStartup", "true");
}

@Parameterized.Parameters
public static Collection<MemoryMeter.Guess> guesses() {

Expand Down
4 changes: 2 additions & 2 deletions test/org/github/jamm/jmh/BenchmarkMeasureInstance.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
@BenchmarkMode(Mode.AverageTime)
@State(Scope.Thread)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public class BenchmarkMeasureInstance
{
public class BenchmarkMeasureInstance {

@Param({"INSTRUMENTATION", "INSTRUMENTATION_AND_SPECIFICATION", "SPECIFICATION", "UNSAFE"})
private String guess;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.Arrays;
import java.util.List;

import org.junit.BeforeClass;
import org.junit.Test;

import org.github.jamm.MemoryMeter.Guess;
Expand All @@ -16,6 +17,11 @@

public class MemoryMeterStrategiesTest {

@BeforeClass
public static void logInfoAtStartup() {
System.setProperty("org.github.jamm.strategies.LogInfoAtStartup", "true");
}

@Test
public void testInvalidEmptyGuessList() {
MemoryMeterStrategies strategies = MemoryMeterStrategies.getInstance();
Expand Down
6 changes: 6 additions & 0 deletions test/org/github/jamm/strategies/MemoryMeterStrategyTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
Expand All @@ -34,6 +35,11 @@
@RunWith(Parameterized.class)
public class MemoryMeterStrategyTest {

@BeforeClass
public static void logInfoAtStartup() {
System.setProperty("org.github.jamm.strategies.LogInfoAtStartup", "true");
}

private final MemoryMeter.Guess guess;

private MemoryMeter tested;
Expand Down
6 changes: 6 additions & 0 deletions test/org/github/jamm/string/StringMeterTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@
@RunWith(Parameterized.class)
public class StringMeterTest {

@BeforeClass
public static void logInfoAtStartup() {
System.setProperty("org.github.jamm.strategies.LogInfoAtStartup", "true");
}

@BeforeClass
public static void turnOffStringOptimization() {
System.setProperty("org.github.jamm.string.Optimize", "false");
Expand Down Expand Up @@ -51,6 +56,7 @@ public void testMeasureDeepString() {
"...... really ...... really .... really ... really .... longuer",
"with a chinese character: 我"};

// The optimization is disabled for the MemoryMeter but not for the StringMeter which does not take into account the ENABLED field.
MemoryMeter reference = MemoryMeter.builder().withGuessing(MemoryMeter.Guess.INSTRUMENTATION).build();
assertFalse(MemoryMeter.useStringOptimization());
StringMeter stringMeter = StringMeter.newInstance();
Expand Down

0 comments on commit 867d781

Please sign in to comment.