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 abstract class implements a simple counter (counting some 023 * integer (long) value for each phase). 024 */ 025@Uninterruptible 026public 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 * @return the current value of this counter 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}