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  */
  23 package org.graalvm.compiler.debug.test;
  24 
  25 import static org.junit.Assert.assertEquals;
  26 import static org.junit.Assert.assertTrue;
  27 
  28 import java.lang.management.ThreadMXBean;
  29 
  30 import org.junit.Assert;
  31 import org.junit.Assume;
  32 import org.junit.Before;
  33 import org.junit.Test;
  34 
  35 import org.graalvm.compiler.debug.Debug;
  36 import org.graalvm.compiler.debug.DebugCloseable;
  37 import org.graalvm.compiler.debug.DebugConfig;
  38 import org.graalvm.compiler.debug.DebugConfigScope;
  39 import org.graalvm.compiler.debug.DebugTimer;
  40 import org.graalvm.compiler.debug.Management;
  41 
  42 @SuppressWarnings("try")
  43 public 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 }