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.jikesrvm.adaptive.measurements.instrumentation; 014 015 import java.util.Hashtable; 016 import org.jikesrvm.VM; 017 import org.jikesrvm.adaptive.measurements.Reportable; 018 import org.jikesrvm.compilers.opt.InstrumentedEventCounterManager; 019 import org.jikesrvm.compilers.opt.ir.Instruction; 020 021 /** 022 * A generic data object that maps strings to counters. The key 023 * method is "Instruction getCounterInstructionForEvent(String)" 024 * which, given a string, returns a counter instruction that 025 * increments the corresponding counter for that string. 026 */ 027 public class StringEventCounterData extends ManagedCounterData implements Reportable { 028 029 static final boolean DEBUG = false; 030 031 /** 032 * Constructor 033 * 034 * @param manager The manager that will provide the counter space 035 **/ 036 StringEventCounterData(InstrumentedEventCounterManager manager, String name) { 037 // Call superclass constructor 038 super(manager); 039 040 dataName = name; 041 } 042 043 /** 044 * Given a string, find or create the counter associated and return 045 * and instruction to increment that counter. 046 * 047 * @param event The name of the event 048 * @return An instruction to increment the count associated with the event. 049 */ 050 public Instruction getCounterInstructionForEvent(String event) { 051 return getCounterInstructionForEvent(event, 1.0); 052 } 053 054 /** 055 * Given a string, find or create the counter associated and return 056 * and instruction to increment that counter. 057 * 058 * @param event The name of the event 059 * @param incrementValue The value to add to counter 060 * @return An instruction that will update the count associated with the event. 061 */ 062 public Instruction getCounterInstructionForEvent(String event, double incrementValue) { 063 064 // Get (or create) the counter for this string and return it. 065 int counterIdx = getOrCreateCounterIndexForString(event); 066 067 return createEventCounterInstruction(counterIdx, incrementValue); 068 } 069 070 /** 071 * Convert a double to string with maximum precision. 072 * @param num double to convert 073 */ 074 protected static String doubleToString(double num) { 075 long whole = (long) num; 076 if (whole == Long.MAX_VALUE || whole == Long.MIN_VALUE) { 077 return Double.toString(whole); 078 } 079 double fract = Math.abs(num - whole); 080 String res = Long.toString(whole); 081 if (fract != 0.0) { 082 String f2s = Double.toString(fract + 1.0); 083 res += f2s.substring(1); 084 } 085 return res; 086 } 087 088 /** 089 * Print a report at the end of execution 090 */ 091 @Override 092 public void report() { 093 // Turn off future instrumentation to avoid hanging during 094 // iteration 095 Instrumentation.disableInstrumentation(); 096 097 VM.sysWrite("Printing " + dataName + ":\n"); 098 VM.sysWrite("--------------------------------------------------\n"); 099 double total = 0; 100 for (String stringName : stringToCounterMap.keySet()) { 101 int counterIdx = getCounterIndexForString(stringName); 102 double counterVal = getCounter(counterIdx); 103 VM.sysWrite(doubleToString(counterVal) + " " + stringName + "\n"); 104 total += counterVal; 105 } 106 VM.sysWrite("Total: " + doubleToString(total) + "\n"); 107 } 108 109 /** 110 * For a given string, return the number of the counter associated 111 * with this string. If this string doesn't already have a counter, 112 * reserve one. 113 * 114 * @param str The string for which you want the counter number 115 * @return The counter number for this string 116 117 */ 118 public int getOrCreateCounterIndexForString(String str) { 119 120 int counterIdx = getCounterIndexForString(str); 121 if (counterIdx == -1) { 122 // Use new counter 123 counterIdx = ++eventNumber; 124 // remember it, and return it 125 stringToCounterMap.put(str, eventNumber); 126 } 127 128 return counterIdx; 129 } 130 131 /** 132 * For a given string, return the number of the counter associated 133 * with this string. Ideally this number would be completely hidden 134 * from the outside world, but for efficiency it is made public. 135 * 136 * @param str The string for which you want the counter number 137 * @return The counter number for this string, or -1 if the string has no 138 counter associated with it. 139 */ 140 public int getCounterIndexForString(String str) { 141 142 int counter = -1; 143 Integer counterNum = stringToCounterMap.get(str); 144 if (counterNum != null) { 145 counter = counterNum; 146 } 147 148 return counter; 149 } 150 151 @Override 152 public void reset() { 153 for (String stringName : stringToCounterMap.keySet()) { 154 int counterIdx = getCounterIndexForString(stringName); 155 setCounter(counterIdx, 0.0); 156 } 157 } 158 159 /** 160 * Map strings to a counter location 161 */ 162 protected final Hashtable<String, Integer> stringToCounterMap = new Hashtable<String, Integer>(); 163 164 /** 165 * A string description of this data; 166 */ 167 final String dataName; 168 169 /** 170 * Used to keep track of how many counters have been used so far. 171 */ 172 int eventNumber = -1; 173 174 } 175 176