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 */
013 package org.mmtk.utility.statistics;
014
015 import org.mmtk.utility.Log;
016
017 import org.mmtk.vm.VM;
018
019 import 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
026 public 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 }