1/*
2 * Copyright (c) 2013, 2015, 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 */
23package org.graalvm.compiler.debug.test;
24
25import static org.junit.Assert.assertEquals;
26import static org.junit.Assert.assertTrue;
27
28import java.lang.management.ThreadMXBean;
29
30import org.junit.Assert;
31import org.junit.Assume;
32import org.junit.Before;
33import org.junit.Test;
34
35import org.graalvm.compiler.debug.Debug;
36import org.graalvm.compiler.debug.DebugCloseable;
37import org.graalvm.compiler.debug.DebugConfig;
38import org.graalvm.compiler.debug.DebugConfigScope;
39import org.graalvm.compiler.debug.DebugTimer;
40import org.graalvm.compiler.debug.Management;
41
42@SuppressWarnings("try")
43public class DebugTimerTest {
44
45    private static final ThreadMXBean threadMXBean = Management.getThreadMXBean();
46
47    @Before
48    public void checkCapabilities() {
49        Assume.assumeTrue("skipping management interface test", threadMXBean.isCurrentThreadCpuTimeSupported());
50    }
51
52    /**
53     * Actively spins the current thread for at least a given number of milliseconds in such a way
54     * that timers for the current thread keep ticking over.
55     *
56     * @return the number of milliseconds actually spent spinning which is guaranteed to be >=
57     *         {@code ms}
58     */
59    private static long spin(long ms) {
60        long start = threadMXBean.getCurrentThreadCpuTime();
61        do {
62            long durationMS = (threadMXBean.getCurrentThreadCpuTime() - start) / 1000;
63            if (durationMS >= ms) {
64                return durationMS;
65            }
66        } while (true);
67    }
68
69    @Test
70    public void test1() {
71        DebugConfig debugConfig = Debug.fixedConfig(0, 0, false, false, true, false, false, null, null, System.out);
72        try (DebugConfigScope dcs = new DebugConfigScope(debugConfig); Debug.Scope s = Debug.scope("DebugTimerTest")) {
73
74            DebugTimer timerA = Debug.timer("TimerA");
75            DebugTimer timerB = Debug.timer("TimerB");
76
77            long spinA;
78            long spinB;
79
80            try (DebugCloseable a1 = timerA.start()) {
81                spinA = spin(50);
82                try (DebugCloseable b1 = timerB.start()) {
83                    spinB = spin(50);
84                }
85            }
86
87            Assert.assertTrue(timerB.getCurrentValue() < timerA.getCurrentValue());
88            if (timerA.getFlat() != null && timerB.getFlat() != null) {
89                assertTrue(spinB >= spinA || timerB.getFlat().getCurrentValue() < timerA.getFlat().getCurrentValue());
90                assertEquals(timerA.getFlat().getCurrentValue(), timerA.getCurrentValue() - timerB.getFlat().getCurrentValue(), 10D);
91            }
92        }
93    }
94
95    @Test
96    public void test2() {
97        DebugConfig debugConfig = Debug.fixedConfig(0, 0, false, false, true, false, false, null, null, System.out);
98        try (DebugConfigScope dcs = new DebugConfigScope(debugConfig); Debug.Scope s = Debug.scope("DebugTimerTest")) {
99            DebugTimer timerC = Debug.timer("TimerC");
100            try (DebugCloseable c1 = timerC.start()) {
101                spin(50);
102                try (DebugCloseable c2 = timerC.start()) {
103                    spin(50);
104                    try (DebugCloseable c3 = timerC.start()) {
105                        spin(50);
106                        try (DebugCloseable c4 = timerC.start()) {
107                            spin(50);
108                            try (DebugCloseable c5 = timerC.start()) {
109                                spin(50);
110                            }
111                        }
112                    }
113                }
114            }
115            if (timerC.getFlat() != null) {
116                assertEquals(timerC.getFlat().getCurrentValue(), timerC.getCurrentValue());
117            }
118        }
119    }
120
121    @Test
122    public void test3() {
123        DebugConfig debugConfig = Debug.fixedConfig(0, 0, false, false, true, false, false, null, null, System.out);
124        try (DebugConfigScope dcs = new DebugConfigScope(debugConfig); Debug.Scope s = Debug.scope("DebugTimerTest")) {
125
126            DebugTimer timerD = Debug.timer("TimerD");
127            DebugTimer timerE = Debug.timer("TimerE");
128
129            long spinD1;
130            long spinE;
131
132            try (DebugCloseable d1 = timerD.start()) {
133                spinD1 = spin(50);
134                try (DebugCloseable e1 = timerE.start()) {
135                    spinE = spin(50);
136                    try (DebugCloseable d2 = timerD.start()) {
137                        spin(50);
138                        try (DebugCloseable d3 = timerD.start()) {
139                            spin(50);
140                        }
141                    }
142                }
143            }
144
145            Assert.assertTrue(timerE.getCurrentValue() < timerD.getCurrentValue());
146            if (timerD.getFlat() != null && timerE.getFlat() != null) {
147                assertTrue(spinE >= spinD1 || timerE.getFlat().getCurrentValue() < timerD.getFlat().getCurrentValue());
148                assertEquals(timerD.getFlat().getCurrentValue(), timerD.getCurrentValue() - timerE.getFlat().getCurrentValue(), 10D);
149            }
150        }
151    }
152}
153