diff test/gc/survivorAlignment/AlignmentHelper.java @ 20804:7848fc12602b

Merge with jdk8u40-b25
author Gilles Duboscq <gilles.m.duboscq@oracle.com>
date Tue, 07 Apr 2015 14:58:49 +0200
parents 4b7c96fba3d8
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/gc/survivorAlignment/AlignmentHelper.java	Tue Apr 07 14:58:49 2015 +0200
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.lang.management.MemoryPoolMXBean;
+import java.util.Optional;
+
+import sun.hotspot.WhiteBox;
+
+/**
+ * Helper class aimed to provide information about alignment of objects in
+ * particular heap space, expected memory usage after objects' allocation so on.
+ */
+public class AlignmentHelper {
+    private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+
+    private static final long OBJECT_ALIGNMENT_IN_BYTES_FOR_32_VM = 8L;
+
+    /**
+     * Max relative allowed actual memory usage deviation from expected memory
+     * usage.
+     */
+    private static final float MAX_RELATIVE_DEVIATION = 0.05f; // 5%
+
+    public static final long OBJECT_ALIGNMENT_IN_BYTES = Optional.ofNullable(
+            AlignmentHelper.WHITE_BOX.getIntxVMFlag("ObjectAlignmentInBytes"))
+            .orElse(AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES_FOR_32_VM);
+
+    public static final long SURVIVOR_ALIGNMENT_IN_BYTES = Optional.ofNullable(
+            AlignmentHelper.WHITE_BOX.getIntxVMFlag("SurvivorAlignmentInBytes"))
+            .orElseThrow(() ->new AssertionError(
+                    "Unable to get SurvivorAlignmentInBytes value"));
+    /**
+     * Min amount of memory that will be occupied by an object.
+     */
+    public static final long MIN_OBJECT_SIZE
+            = AlignmentHelper.WHITE_BOX.getObjectSize(new Object());
+    /**
+     * Min amount of memory that will be occupied by an empty byte array.
+     */
+    public static final long MIN_ARRAY_SIZE
+            = AlignmentHelper.WHITE_BOX.getObjectSize(new byte[0]);
+
+    /**
+     * Precision at which actual memory usage in a heap space represented by
+     * this sizing helper could be measured.
+     */
+    private final long memoryUsageMeasurementPrecision;
+    /**
+     * Min amount of memory that will be occupied by an object allocated in a
+     * heap space represented by this sizing helper.
+     */
+    private final long minObjectSizeInThisSpace;
+    /**
+     * Object's alignment in a heap space represented by this sizing helper.
+     */
+    private final long objectAlignmentInThisRegion;
+    /**
+     * MemoryPoolMXBean associated with a heap space represented by this sizing
+     * helper.
+     */
+    private final MemoryPoolMXBean poolMXBean;
+
+    private static long alignUp(long value, long alignment) {
+        return ((value - 1) / alignment + 1) * alignment;
+    }
+
+    protected AlignmentHelper(long memoryUsageMeasurementPrecision,
+            long objectAlignmentInThisRegion, long minObjectSizeInThisSpace,
+            MemoryPoolMXBean poolMXBean) {
+        this.memoryUsageMeasurementPrecision = memoryUsageMeasurementPrecision;
+        this.minObjectSizeInThisSpace = minObjectSizeInThisSpace;
+        this.objectAlignmentInThisRegion = objectAlignmentInThisRegion;
+        this.poolMXBean = poolMXBean;
+    }
+
+    /**
+     * Returns how many objects have to be allocated to fill
+     * {@code memoryToFill} bytes in this heap space using objects of size
+     * {@code objectSize}.
+     */
+    public int getObjectsCount(long memoryToFill, long objectSize) {
+        return (int) (memoryToFill / getObjectSizeInThisSpace(objectSize));
+    }
+
+    /**
+     * Returns amount of memory that {@code objectsCount} of objects with size
+     * {@code objectSize} will occupy this this space after allocation.
+     */
+    public long getExpectedMemoryUsage(long objectSize, int objectsCount) {
+        long correctedObjectSize = getObjectSizeInThisSpace(objectSize);
+        return AlignmentHelper.alignUp(correctedObjectSize * objectsCount,
+                memoryUsageMeasurementPrecision);
+    }
+
+    /**
+     * Returns current memory usage in this heap space.
+     */
+    public long getActualMemoryUsage() {
+        return poolMXBean.getUsage().getUsed();
+    }
+
+    /**
+     * Returns maximum memory usage deviation from {@code expectedMemoryUsage}
+     * given the max allowed relative deviation equal to
+     * {@code relativeDeviation}.
+     *
+     * Note that value returned by this method is aligned according to
+     * memory measurement precision for this heap space.
+     */
+    public long getAllowedMemoryUsageDeviation(long expectedMemoryUsage) {
+        long unalignedDeviation = (long) (expectedMemoryUsage *
+                AlignmentHelper.MAX_RELATIVE_DEVIATION);
+        return AlignmentHelper.alignUp(unalignedDeviation,
+                memoryUsageMeasurementPrecision);
+    }
+
+    /**
+     * Returns amount of memory that will be occupied by an object with size
+     * {@code objectSize} in this heap space.
+     */
+    public long getObjectSizeInThisSpace(long objectSize) {
+        objectSize = Math.max(objectSize, minObjectSizeInThisSpace);
+
+        long alignedObjectSize = AlignmentHelper.alignUp(objectSize,
+                objectAlignmentInThisRegion);
+        long sizeDiff = alignedObjectSize - objectSize;
+
+        // If there is not enough space to fit padding object, then object will
+        // be aligned to {@code 2 * objectAlignmentInThisRegion}.
+        if (sizeDiff >= AlignmentHelper.OBJECT_ALIGNMENT_IN_BYTES
+                && sizeDiff < AlignmentHelper.MIN_OBJECT_SIZE) {
+            alignedObjectSize += AlignmentHelper.MIN_OBJECT_SIZE;
+            alignedObjectSize = AlignmentHelper.alignUp(alignedObjectSize,
+                    objectAlignmentInThisRegion);
+        }
+
+        return alignedObjectSize;
+    }
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+
+        builder.append(String.format("AlignmentHelper for memory pool '%s':%n",
+                poolMXBean.getName()));
+        builder.append(String.format("Memory usage measurement precision: %d%n",
+                memoryUsageMeasurementPrecision));
+        builder.append(String.format("Min object size in this space: %d%n",
+                minObjectSizeInThisSpace));
+        builder.append(String.format("Object alignment in this space: %d%n",
+                objectAlignmentInThisRegion));
+
+        return builder.toString();
+    }
+}