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 abstract class implements a simple counter (counting some
023 * integer (long) value for each phase).
024 */
025 @Uninterruptible
026 public abstract class LongCounter extends Counter {
027
028 /****************************************************************************
029 *
030 * Instance variables
031 */
032
033 /**
034 *
035 */
036 private final long[] count;
037
038 private long startValue = 0;
039 protected long totalCount = 0;
040 private boolean running = false;
041
042 /****************************************************************************
043 *
044 * Initialization
045 */
046
047 /**
048 * Constructor
049 *
050 * @param name The name to be associated with this counter
051 */
052 LongCounter(String name) {
053 this(name, true, false);
054 }
055
056 /**
057 * Constructor
058 *
059 * @param name The name to be associated with this counter
060 * @param start True if this counter is to be implicitly started
061 * when <code>startAll()</code> is called (otherwise the counter
062 * must be explicitly started).
063 */
064 LongCounter(String name, boolean start) {
065 this(name, start, false);
066 }
067
068 /**
069 * Constructor
070 *
071 * @param name The name to be associated with this counter
072 * @param start True if this counter is to be implicitly started
073 * when <code>startAll()</code> is called (otherwise the counter
074 * must be explicitly started).
075 * @param mergephases True if this counter does not separately
076 * report GC and Mutator phases.
077 */
078 LongCounter(String name, boolean start, boolean mergephases) {
079 super(name, start, mergephases);
080 count = new long[Stats.MAX_PHASES];
081 }
082
083 /****************************************************************************
084 *
085 * Counter-specific methods
086 */
087
088 /**
089 *
090 */
091 protected abstract long getCurrentValue();
092
093 /****************************************************************************
094 *
095 * Generic counter control methods: start, stop, print etc
096 */
097
098 /**
099 * {@inheritDoc}
100 */
101 @Override
102 public void start() {
103 if (!Stats.gatheringStats) return;
104 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(!running);
105 running = true;
106 startValue = getCurrentValue();
107 }
108
109 @Override
110 public void stop() {
111 if (!Stats.gatheringStats) return;
112 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert(running);
113 running = false;
114 long delta = getCurrentValue() - startValue;
115 count[Stats.phase] += delta;
116 totalCount += delta;
117 }
118
119 /**
120 * The phase has changed (from GC to mutator or mutator to GC).
121 * Take action with respect to the last phase if necessary.
122 * <b>Do nothing in this case.</b>
123 *
124 * @param oldPhase The last phase
125 */
126 @Override
127 protected void phaseChange(int oldPhase) {
128 if (running) {
129 long now = getCurrentValue();
130 long delta = now - startValue;
131 count[oldPhase] += delta;
132 totalCount += delta;
133 startValue = now;
134 }
135 }
136
137 /**
138 * {@inheritDoc}
139 * Print '0' for {@code false}, '1' for {@code true}.
140 */
141 @Override
142 protected final void printCount(int phase) {
143 if (VM.VERIFY_ASSERTIONS && mergePhases())
144 if (VM.VERIFY_ASSERTIONS) VM.assertions._assert((phase | 1) == (phase + 1));
145 if (mergePhases())
146 printValue(count[phase] + count[phase + 1]);
147 else
148 printValue(count[phase]);
149 }
150
151 @Override
152 public final void printTotal() {
153 printValue(totalCount);
154 }
155
156
157 /**
158 * Get the total as at the lasts phase
159 *
160 * @return The total as at the last phase
161 */
162 long getLastTotal() {
163 return totalCount;
164 }
165
166 @Override
167 protected final void printTotal(boolean mutator) {
168 long total = 0;
169 for (int p = (mutator) ? 0 : 1; p <= Stats.phase; p += 2) {
170 total += count[p];
171 }
172 printValue(total);
173 }
174
175 @Override
176 protected final void printMin(boolean mutator) {
177 int p = (mutator) ? 0 : 1;
178 long min = count[p];
179 for (; p < Stats.phase; p += 2) {
180 if (count[p] < min) min = count[p];
181 }
182 printValue(min);
183 }
184
185 @Override
186 protected final void printMax(boolean mutator) {
187 int p = (mutator) ? 0 : 1;
188 long max = count[p];
189 for (; p < Stats.phase; p += 2) {
190 if (count[p] > max) max = count[p];
191 }
192 printValue(max);
193 }
194
195 /**
196 * Print the given value
197 *
198 * @param value The value to be printed
199 */
200 void printValue(long value) {
201 Log.write(value);
202 }
203 }