001/* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013package org.mmtk.utility.statistics; 014 015import org.mmtk.utility.Log; 016 017import org.mmtk.vm.VM; 018 019import org.vmmagic.pragma.*; 020 021/** 022 * This class implements a simple event counter (counting number 023 * events that occur for each phase). 024 */ 025@Uninterruptible 026public class EventCounter extends Counter { 027 028 /**************************************************************************** 029 * 030 * Instance variables 031 */ 032 033 /** 034 * 035 */ 036 private final long[] count; 037 038 protected long currentCount = 0; 039 private boolean running = false; 040 041 /**************************************************************************** 042 * 043 * Initialization 044 */ 045 046 /** 047 * Constructor 048 * 049 * @param name The name to be associated with this counter 050 */ 051 public EventCounter(String name) { 052 this(name, true, false); 053 } 054 055 /** 056 * Constructor 057 * 058 * @param name The name to be associated with this counter 059 * @param start True if this counter is to be implicitly started 060 * when <code>startAll()</code> is called (otherwise the counter 061 * must be explicitly started). 062 */ 063 public EventCounter(String name, boolean start) { 064 this(name, start, false); 065 } 066 067 /** 068 * Constructor 069 * 070 * @param name The name to be associated with this counter 071 * @param start {@code true} if this counter is to be implicitly started 072 * when <code>startAll()</code> is called (otherwise the counter 073 * must be explicitly started). 074 * @param mergephases {@code true} if this counter does not separately 075 * report GC and Mutator phases. 076 */ 077 public EventCounter(String name, boolean start, boolean mergephases) { 078 super(name, start, mergephases); 079 count = new long[Stats.MAX_PHASES]; 080 } 081 082 /**************************************************************************** 083 * 084 * Counter-specific methods 085 */ 086 087 /** 088 * Increment the event counter 089 */ 090 public void inc() { 091 if (running) inc(1); 092 } 093 094 /** 095 * Increment the event counter by <code>value</code> 096 * 097 * @param value The amount by which the counter should be incremented. 098 */ 099 public void inc(int value) { 100 if (running) currentCount += value; 101 } 102 103 /**************************************************************************** 104 * 105 * Generic counter control methods: start, stop, print etc 106 */ 107 108 /** 109 * {@inheritDoc} 110 */ 111 @Override 112 protected void start() { 113 if (!Stats.gatheringStats) return; 114 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!running); 115 running = true; 116 } 117 118 @Override 119 protected void stop() { 120 if (!Stats.gatheringStats) return; 121 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(running); 122 count[Stats.phase] = currentCount; 123 currentCount = 0; 124 running = false; 125 } 126 127 /** 128 * The phase has changed (from GC to mutator or mutator to GC). 129 * Take action with respect to the last phase if necessary. 130 * <b>Do nothing in this case.</b> 131 * 132 * @param oldPhase The last phase 133 */ 134 @Override 135 void phaseChange(int oldPhase) { 136 if (running) { 137 count[oldPhase] = currentCount; 138 currentCount = 0; 139 } 140 } 141 142 /** 143 * {@inheritDoc} 144 * Print '0' for {@code false}, '1' for {@code true}. 145 */ 146 @Override 147 protected final void printCount(int phase) { 148 if (VM.VERIFY_ASSERTIONS && mergePhases()) 149 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((phase | 1) == (phase + 1)); 150 if (mergePhases()) 151 printValue(count[phase] + count[phase + 1]); 152 else 153 printValue(count[phase]); 154 } 155 156 /** 157 * Print the current value for this counter (mid-phase) 158 */ 159 public final void printCurrent() { 160 printValue(currentCount); 161 } 162 163 @Override 164 public final void printTotal() { 165 long total = 0; 166 for (int p = 0; p <= Stats.phase; p++) { 167 total += count[p]; 168 } 169 printValue(total); 170 } 171 172 @Override 173 protected final void printTotal(boolean mutator) { 174 long total = 0; 175 for (int p = (mutator) ? 0 : 1; p <= Stats.phase; p += 2) { 176 total += count[p]; 177 } 178 printValue(total); 179 } 180 181 @Override 182 protected final void printMin(boolean mutator) { 183 int p = (mutator) ? 0 : 1; 184 long min = count[p]; 185 for (; p < Stats.phase; p += 2) { 186 if (count[p] < min) min = count[p]; 187 } 188 printValue(min); 189 } 190 191 @Override 192 protected final void printMax(boolean mutator) { 193 int p = (mutator) ? 0 : 1; 194 long max = count[p]; 195 for (; p < Stats.phase; p += 2) { 196 if (count[p] > max) max = count[p]; 197 } 198 printValue(max); 199 } 200 201 /** 202 * Print the given value 203 * 204 * @param value The value to be printed 205 */ 206 void printValue(long value) { 207 Log.write(value); 208 } 209 210 @Override 211 public void printLast() { 212 if (Stats.phase > 0) printCount(Stats.phase - 1); 213 } 214}