1 /*
   2  * Copyright (c) 2018, Google and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 package MyPackage;
  25 
  26 /**
  27  * @test
  28  * @build Frame HeapMonitor
  29  * @summary Verifies the JVMTI Heap Monitor sampling via object allocation.
  30  * @compile HeapMonitorStatObjectCorrectnessTest.java
  31  * @run main/othervm/native -agentlib:HeapMonitorTest MyPackage.HeapMonitorStatObjectCorrectnessTest
  32  */
  33 
  34 /** This test is checking the object allocation path works with heap sampling. */
  35 public class HeapMonitorStatObjectCorrectnessTest {
  36 
  37   // Do 200000 iterations and expect maxIteration / multiplier samples.
  38   private static final int maxIteration = 200000;
  39   private static BigObject obj;
  40 
  41   private native static boolean statsHaveExpectedNumberSamples(int expected, int percentError);
  42 
  43   private static void allocate() {
  44     for (int j = 0; j < maxIteration; j++) {
  45       obj = new BigObject();
  46     }
  47   }
  48 
  49   private static void testBigAllocationRate() {
  50     final int sizeObject = 1400;
  51 
  52     // 111 is as good a number as any.
  53     final int samplingMultiplier = 111;
  54     HeapMonitor.setSamplingRate(samplingMultiplier * sizeObject);
  55 
  56     emptyStorage();
  57     allocate();
  58 
  59     // For simplifications, the code is allocating:
  60     //   (BigObject size) * maxIteration.
  61     //
  62     // We ignore the class memory usage apart from field memory usage for BigObject. BigObject
  63     // allocates 250 long, so 2000 bytes, so whatever is used for the class is negligible.
  64     //
  65     // That means that with maxIterations, the loop in the method allocate requests:
  66     //    maxIterations * 2000 bytes.
  67     //
  68     // Via the enable sampling, the code requests a sample every samplingMultiplier * sizeObject bytes.
  69     //
  70     // Therefore, the expected sample number is:
  71     //   (maxIterations * sizeObject) / (samplingMultiplier * sizeObject);
  72     //
  73     // Which becomes:
  74     //   maxIterations / samplingMultiplier
  75     double expected = maxIteration;
  76     expected /= samplingMultiplier;
  77 
  78     // 10% error ensures a sanity test without becoming flaky.
  79     if (!HeapMonitor.statsHaveExpectedNumberSamples((int) expected, 10)) {
  80       throw new RuntimeException("Statistics should show about " + expected + " samples.");
  81     }
  82   }
  83 
  84   private static void emptyStorage() {
  85     HeapMonitor.resetEventStorage();
  86 
  87     if (!HeapMonitor.eventStorageIsEmpty()) {
  88       throw new RuntimeException("Statistics should be null to begin with.");
  89     }
  90   }
  91 
  92   private static void testEveryAllocationSampled() {
  93     // 0 means sample every allocation.
  94     HeapMonitor.setSamplingRate(0);
  95 
  96     emptyStorage();
  97     allocate();
  98 
  99     double expected = maxIteration;
 100 
 101     // 10% error ensures a sanity test without becoming flaky.
 102     if (!HeapMonitor.statsHaveExpectedNumberSamples((int) expected, 10)) {
 103       throw new RuntimeException("Statistics should show about " + expected + " samples.");
 104     }
 105   }
 106 
 107   public static void main(String[] args) {
 108     HeapMonitor.enableSamplingEvents();
 109 
 110     testBigAllocationRate();
 111     testEveryAllocationSampled();
 112   }
 113 
 114   /**
 115    * Big class on purpose to just be able to ignore the class memory space overhead.
 116    *
 117    * Class contains 175 long fields, so 175 * 8 = 1400 bytes.
 118    */
 119   private static class BigObject {
 120     private long a0_0, a0_1, a0_2, a0_3, a0_4, a0_5, a0_6, a0_7, a0_8, a0_9;
 121     private long a1_0, a1_1, a1_2, a1_3, a1_4, a1_5, a1_6, a1_7, a1_8, a1_9;
 122     private long a2_0, a2_1, a2_2, a2_3, a2_4, a2_5, a2_6, a2_7, a2_8, a2_9;
 123     private long a3_0, a3_1, a3_2, a3_3, a3_4, a3_5, a3_6, a3_7, a3_8, a3_9;
 124     private long a4_0, a4_1, a4_2, a4_3, a4_4, a4_5, a4_6, a4_7, a4_8, a4_9;
 125     private long a5_0, a5_1, a5_2, a5_3, a5_4, a5_5, a5_6, a5_7, a5_8, a5_9;
 126     private long a6_0, a6_1, a6_2, a6_3, a6_4, a6_5, a6_6, a6_7, a6_8, a6_9;
 127     private long a7_0, a7_1, a7_2, a7_3, a7_4, a7_5, a7_6, a7_7, a7_8, a7_9;
 128     private long a8_0, a8_1, a8_2, a8_3, a8_4, a8_5, a8_6, a8_7, a8_8, a8_9;
 129     private long a9_0, a9_1, a9_2, a9_3, a9_4, a9_5, a9_6, a9_7, a9_8, a9_9;
 130     private long a10_0, a10_1, a10_2, a10_3, a10_4, a10_5, a10_6, a10_7, a10_8, a10_9;
 131     private long a11_0, a11_1, a11_2, a11_3, a11_4, a11_5, a11_6, a11_7, a11_8, a11_9;
 132     private long a12_0, a12_1, a12_2, a12_3, a12_4, a12_5, a12_6, a12_7, a12_8, a12_9;
 133     private long a13_0, a13_1, a13_2, a13_3, a13_4, a13_5, a13_6, a13_7, a13_8, a13_9;
 134     private long a14_0, a14_1, a14_2, a14_3, a14_4, a14_5, a14_6, a14_7, a14_8, a14_9;
 135     private long a15_0, a15_1, a15_2, a15_3, a15_4, a15_5, a15_6, a15_7, a15_8, a15_9;
 136     private long a16_0, a16_1, a16_2, a16_3, a16_4, a16_5, a16_6, a16_7, a16_8, a16_9;
 137     private long a17_0, a17_1, a17_2, a17_3, a17_4;
 138   }
 139 }