1/*
2 * Copyright (c) 2017, Oracle 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
24import java.lang.management.ManagementFactory;
25import utils.GarbageProducer;
26import common.TmTool;
27import utils.JstatResults;
28
29/**
30 * Base class for jstat testing which uses GarbageProducer to allocate garbage.
31 */
32public class GarbageProducerTest {
33
34    // Iterations of measurement to get consistent value of counters and jstat.
35    private final static int ITERATIONS = 10;
36    private final static float TARGET_MEMORY_USAGE = 0.7f;
37    private final static float MEASUREMENT_TOLERANCE = 0.05f;
38    private final GarbageProducer garbageProducer;
39    private final TmTool<? extends JstatResults> jstatTool;
40
41    public GarbageProducerTest(TmTool<? extends JstatResults> tool) {
42        garbageProducer = new GarbageProducer(TARGET_MEMORY_USAGE);
43        // We will be running jstat tool
44        jstatTool = tool;
45    }
46
47    public void run() throws Exception {
48        // Run once and get the  results asserting that they are reasonable
49        JstatResults measurement1 = jstatTool.measure();
50        measurement1.assertConsistency();
51        // Eat metaspace and heap then run the tool again and get the results  asserting that they are reasonable
52        System.gc();
53        garbageProducer.allocateMetaspaceAndHeap();
54        // Collect garbage. Also update VM statistics
55        System.gc();
56        int i = 0;
57        long collectionCountBefore = getCollectionCount();
58        JstatResults measurement2 = jstatTool.measure();
59        do {
60            System.out.println("Measurement #" + i);
61            long currentCounter = getCollectionCount();
62            // Check if GC cycle occured during measurement
63            if (currentCounter == collectionCountBefore) {
64                measurement2.assertConsistency();
65                checkOldGenMeasurement(measurement2);
66                return;
67            } else {
68                System.out.println("GC happened during measurement.");
69            }
70            collectionCountBefore = getCollectionCount();
71            measurement2 = jstatTool.measure();
72
73        } while (i++ < ITERATIONS);
74        // Checking will be performed without consistency guarantee.
75        checkOldGenMeasurement(measurement2);
76    }
77
78    private void checkOldGenMeasurement(JstatResults measurement2) {
79        float oldGenAllocationRatio = garbageProducer.getOldGenAllocationRatio() - MEASUREMENT_TOLERANCE;
80        // Assert that space has been utilized accordingly
81        JstatResults.assertSpaceUtilization(measurement2, TARGET_MEMORY_USAGE, oldGenAllocationRatio);
82    }
83
84    private static long getCollectionCount() {
85        return ManagementFactory.getGarbageCollectorMXBeans().stream()
86                .mapToLong(b -> b.getCollectionCount())
87                .sum();
88    }
89}
90