1 salcianu 1.1 // AllocationStatistics.java, created Sat Nov 30 22:21:12 2002 by salcianu 2 salcianu 1.1 // Copyright (C) 2000 Alexandru Salcianu <salcianu@MIT.EDU> 3 salcianu 1.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 salcianu 1.1 package harpoon.Instrumentation.AllocationStatistics; 5 salcianu 1.1 6 salcianu 1.1 import harpoon.ClassFile.HClass; 7 salcianu 1.1 import harpoon.ClassFile.HMethod; 8 salcianu 1.1 import harpoon.ClassFile.Linker; 9 salcianu 1.1 import harpoon.ClassFile.HCodeFactory; 10 salcianu 1.1 import harpoon.Analysis.Quads.CallGraph; 11 salcianu 1.1 import harpoon.IR.Quads.Quad; 12 salcianu 1.1 import harpoon.IR.Quads.QuadVisitor; 13 salcianu 1.1 import harpoon.IR.Quads.Code; 14 salcianu 1.1 import harpoon.Analysis.PointerAnalysis.Debug; 15 salcianu 1.1 16 salcianu 1.5 import harpoon.Util.Util; 17 salcianu 1.5 18 salcianu 1.1 import java.util.Map; 19 salcianu 1.1 import java.util.HashMap; 20 salcianu 1.1 import java.util.Iterator; 21 salcianu 1.1 import java.util.Set; 22 salcianu 1.1 import java.util.Collection; 23 salcianu 1.1 import java.util.Arrays; 24 salcianu 1.1 import java.util.List; 25 salcianu 1.1 import java.util.LinkedList; 26 salcianu 1.1 import java.util.Collection; 27 salcianu 1.1 28 salcianu 1.1 import java.io.BufferedReader; 29 salcianu 1.1 import java.io.FileReader; 30 salcianu 1.1 import java.io.IOException; 31 salcianu 1.1 import java.io.PrintWriter; 32 salcianu 1.1 33 salcianu 1.1 /** 34 salcianu 1.1 * <code>AllocationStatistics</code> reads the output produced by the 35 salcianu 1.1 * allocation instrumentation and offers support for gathering and 36 salcianu 1.1 * displaying statistics about the number of times each allocation 37 salcianu 1.1 * site from an instrumented program was executed. 38 salcianu 1.1 * 39 salcianu 1.1 * @author Alexandru Salcianu <salcianu@MIT.EDU> 40 cananian 1.7 * @version $Id: AllocationStatistics.java,v 1.7 2004/02/08 03:21:32 cananian Exp $ 41 salcianu 1.1 * @see InstrumentAllocs 42 salcianu 1.1 */ 43 salcianu 1.1 public class AllocationStatistics { 44 salcianu 1.2 45 salcianu 1.2 /** Create an <code>AllocationStatistics</code> object. 46 salcianu 1.2 47 salcianu 1.2 @param ani <code>AllocationNumberingInterf</code> object that 48 salcianu 1.2 provides the mapping between allocation sites and globally 49 salcianu 1.2 unique integer IDs. 50 salcianu 1.2 51 salcianu 1.2 @param instrumentationResultFileName name of the file that 52 salcianu 1.2 holds the result of the instrumentation: for each unique ID, 53 salcianu 1.2 the number of times the associated allocation site was 54 salcianu 1.3 executed and the total amount of memory allocated there. */ 55 salcianu 1.2 public AllocationStatistics(AllocationNumberingInterf ani, 56 salcianu 1.2 String instrumentationResultsFileName) { 57 salcianu 1.2 try { 58 salcianu 1.2 this.ani = ani; 59 salcianu 1.3 this.allocID2data = 60 salcianu 1.2 parseInstrumentationResults(instrumentationResultsFileName); 61 salcianu 1.2 } 62 salcianu 1.2 catch(IOException e) { 63 salcianu 1.2 System.err.println("Cannot create AllocStatistics: " + e); 64 salcianu 1.2 System.exit(1); 65 salcianu 1.2 } 66 salcianu 1.2 } 67 salcianu 1.2 68 salcianu 1.2 69 salcianu 1.2 /** Create a <code>AllocationStatistics</code>. 70 salcianu 1.2 71 salcianu 1.3 @param linker <code>Linker</code> used to load the classes. 72 salcianu 1.3 73 salcianu 1.3 @param allocNumberingFileName name of the file that stores the 74 salcianu 1.3 textualized form of the <code>AllocationNumberingStub</code> 75 salcianu 1.3 (that associates to each allocation site a unique integer ID). 76 salcianu 1.3 77 salcianu 1.3 @param instrumentationResultFileName name of the file that 78 salcianu 1.3 holds the result of the instrumentation: for each unique ID, 79 salcianu 1.3 the number of times the associated allocation site was 80 salcianu 1.3 executed. */ 81 salcianu 1.1 public AllocationStatistics(Linker linker, 82 salcianu 1.1 String allocNumberingFileName, 83 salcianu 1.1 String instrumentationResultsFileName) { 84 salcianu 1.1 try { 85 salcianu 1.2 this.ani = 86 salcianu 1.1 new AllocationNumberingStub(linker, allocNumberingFileName); 87 salcianu 1.3 this.allocID2data = 88 salcianu 1.2 parseInstrumentationResults(instrumentationResultsFileName); 89 salcianu 1.1 } 90 salcianu 1.1 catch(IOException e) { 91 salcianu 1.1 System.err.println("Cannot create AllocStatistics: " + e); 92 salcianu 1.1 System.exit(1); 93 salcianu 1.1 } 94 salcianu 1.1 } 95 salcianu 1.1 96 salcianu 1.3 /** data computed by the instrumentation */ 97 salcianu 1.3 private static class AllocData { 98 salcianu 1.3 public AllocData(final long objCount, final long memAmount) { 99 salcianu 1.3 this.objCount = objCount; 100 salcianu 1.3 this.memAmount = memAmount; 101 salcianu 1.3 } 102 salcianu 1.3 public final long objCount; 103 salcianu 1.3 public final long memAmount; 104 salcianu 1.3 } 105 salcianu 1.3 106 salcianu 1.3 107 salcianu 1.1 // provides the map quad -> allocID (an integer) 108 salcianu 1.2 private AllocationNumberingInterf ani; 109 salcianu 1.1 // map allocID -> count 110 salcianu 1.3 private Map/*<Integer,AllocData>*/ allocID2data; 111 salcianu 1.1 112 salcianu 1.1 113 salcianu 1.6 /** Returns the number of times the allocation <code>alloc</code> 114 salcianu 1.1 was executed. 115 salcianu 1.1 116 salcianu 1.1 @param alloc allocation site 117 salcianu 1.1 118 salcianu 1.1 @return number of times <code>alloc</code> was executed */ 119 salcianu 1.3 public long getCount(Quad alloc) { 120 salcianu 1.3 AllocData ad = 121 salcianu 1.3 (AllocData) allocID2data.get(new Integer(ani.allocID(alloc))); 122 salcianu 1.3 return (ad == null) ? 0 : ad.objCount; 123 salcianu 1.3 } 124 salcianu 1.3 125 salcianu 1.3 126 salcianu 1.6 /** Returns the total amount of memory allocated at the allocation 127 salcianu 1.3 <code>alloc</code>. 128 salcianu 1.3 129 salcianu 1.3 @param alloc allocation site 130 salcianu 1.3 131 salcianu 1.3 @return total amount of memory allocated at <code>alloc</code> */ 132 salcianu 1.3 public long getMemAmount(Quad alloc) { 133 salcianu 1.3 AllocData ad = 134 salcianu 1.3 (AllocData) allocID2data.get(new Integer(ani.allocID(alloc))); 135 salcianu 1.3 return (ad == null) ? 0 : ad.memAmount; 136 salcianu 1.6 } 137 salcianu 1.6 138 salcianu 1.6 139 salcianu 1.6 /** Returns the unique ID for <code>alloc</code>. */ 140 salcianu 1.6 public int allocID(Quad alloc) { 141 salcianu 1.6 return ani.allocID(alloc); 142 salcianu 1.1 } 143 salcianu 1.1 144 salcianu 1.1 145 salcianu 1.1 /** Prints statitistics about the allocation sites from the 146 salcianu 1.1 collection <code>allocs</code>. If <code>visitor</code> is 147 salcianu 1.1 non-null, it is called on each allocation site (this way, one 148 salcianu 1.1 can customize the displayed statistics). The allocation sites 149 salcianu 1.1 are listed/visited in the decreasing order of the number of 150 salcianu 1.1 objects allocated there. Sites that allocate too few objects 151 salcianu 1.2 (less than 1% of the total objects) are not considered. */ 152 salcianu 1.1 public void printStatistics(Collection allocs, QuadVisitor visitor) { 153 salcianu 1.1 154 salcianu 1.1 class SiteStat implements Comparable { 155 salcianu 1.3 public final Quad allocSite; 156 salcianu 1.3 public final long allocCount; 157 salcianu 1.3 public final long memAmount; 158 salcianu 1.3 public SiteStat(Quad allocSite, 159 salcianu 1.3 long allocCount, long memAmount) { 160 salcianu 1.3 this.allocSite = allocSite; 161 salcianu 1.3 this.allocCount = allocCount; 162 salcianu 1.3 this.memAmount = memAmount; 163 salcianu 1.1 } 164 salcianu 1.1 public int compareTo(Object o) { 165 salcianu 1.1 if(! (o instanceof SiteStat)) return -1; 166 salcianu 1.1 SiteStat s2 = (SiteStat) o; 167 salcianu 1.3 if (allocCount < s2.allocCount) return +1; 168 salcianu 1.3 else if (allocCount > s2.allocCount) return -1; 169 salcianu 1.1 else return 0; 170 salcianu 1.1 } 171 salcianu 1.1 }; 172 salcianu 1.1 173 salcianu 1.1 int ss_size = 0; 174 cananian 1.7 for(Object allocSiteO : allocs) { 175 cananian 1.7 Quad allocSite = (Quad) allocSiteO; 176 salcianu 1.3 if(getCount(allocSite) != 0) ss_size++; 177 salcianu 1.1 } 178 salcianu 1.1 SiteStat[] ss = new SiteStat[ss_size]; 179 salcianu 1.1 180 salcianu 1.1 long total_count = 0; 181 salcianu 1.1 int i = 0; 182 cananian 1.7 for(Object allocSiteO : allocs) { 183 cananian 1.7 Quad allocSite = (Quad) allocSiteO; 184 salcianu 1.3 long allocCount = getCount(allocSite); 185 salcianu 1.3 if(allocCount != 0) { 186 salcianu 1.3 total_count += allocCount; 187 salcianu 1.3 ss[i++] = new SiteStat(allocSite, allocCount, 188 salcianu 1.3 getMemAmount(allocSite)); 189 salcianu 1.1 } 190 salcianu 1.1 } 191 salcianu 1.1 Arrays.sort(ss); 192 salcianu 1.1 193 salcianu 1.1 long partial_count = 0; 194 salcianu 1.1 System.out.println("Allocation Statistics BEGIN"); 195 salcianu 1.1 for(i = 0; i < ss.length; i++) { 196 salcianu 1.3 Quad site = ss[i].allocSite; 197 salcianu 1.3 long count = ss[i].allocCount; 198 salcianu 1.1 double frac = (count*100.0) / total_count; 199 salcianu 1.1 partial_count += count; 200 salcianu 1.1 System.out.println 201 salcianu 1.5 (Util.code2str(site) + "\n\t" + 202 salcianu 1.3 count + " object(s)\n\t" + 203 salcianu 1.3 ss[i].memAmount + " byte(s)\n\t" + 204 salcianu 1.5 Util.doubleRep(frac, 5, 2) + "% of all objects\n\t" + 205 salcianu 1.1 site.getFactory().getMethod()); 206 salcianu 1.1 if(visitor != null) 207 salcianu 1.1 site.accept(visitor); 208 salcianu 1.1 if((frac < 1) || // don't print sites with < 1% allocations 209 salcianu 1.1 (((double) partial_count / (double) total_count) > 0.90)) { 210 salcianu 1.1 i++; 211 salcianu 1.1 break; 212 salcianu 1.1 } 213 salcianu 1.1 } 214 salcianu 1.1 System.out.println 215 salcianu 1.1 (i + ((i==1) ? " site allocates " : " sites allocate ") + 216 salcianu 1.5 Util.doubleRep((partial_count*100.0) / total_count, 5, 2) + 217 salcianu 1.1 "% of all objects"); 218 salcianu 1.1 System.out.println("Allocation Statistics END"); 219 salcianu 1.1 } 220 salcianu 1.1 221 salcianu 1.1 222 salcianu 1.1 public void printStatistics(Collection allocs) { 223 salcianu 1.1 printStatistics(allocs, null); 224 salcianu 1.1 } 225 salcianu 1.2 226 salcianu 1.2 227 salcianu 1.2 /** Parse the text file produced by an instrumented program. 228 salcianu 1.2 229 salcianu 1.2 @param instrumentationResultsFileName name of the file holding the 230 salcianu 1.2 instrumentation results 231 salcianu 1.2 232 salcianu 1.3 @return map that attaches to each unique ID the data collected 233 salcianu 1.3 by the instrumentation for the corresponding allocation 234 salcianu 1.3 site. */ 235 salcianu 1.3 public static Map/*<Integer,AllocData>*/ parseInstrumentationResults 236 salcianu 1.2 (String instrumentationResultsFileName) throws IOException { 237 salcianu 1.2 BufferedReader br = 238 salcianu 1.2 new BufferedReader(new FileReader(instrumentationResultsFileName)); 239 salcianu 1.3 Map/*<Integer, AllocData>*/ allocID2data = new HashMap(); 240 salcianu 1.2 int size = readInt(br); 241 salcianu 1.2 for(int i = 0; i < size; i++) { 242 salcianu 1.3 long objCount = readLong(br); 243 salcianu 1.3 long memAmount = readLong(br); 244 salcianu 1.3 allocID2data.put 245 salcianu 1.3 (new Integer(i), new AllocData(objCount, memAmount)); 246 salcianu 1.2 } 247 salcianu 1.3 return allocID2data; 248 salcianu 1.2 } 249 salcianu 1.2 250 salcianu 1.2 251 salcianu 1.2 private static int readInt(BufferedReader br) throws IOException { 252 salcianu 1.3 return Integer.parseInt(br.readLine()); 253 salcianu 1.3 } 254 salcianu 1.3 255 salcianu 1.3 private static long readLong(BufferedReader br) throws IOException { 256 salcianu 1.3 return Long.parseLong(br.readLine()); 257 salcianu 1.2 } 258 salcianu 1.2 259 salcianu 1.1 260 salcianu 1.1 /** Return a collection of all the allocation sites (quads) from 261 salcianu 1.1 the methods from the set <code>methods</code>. 262 salcianu 1.1 263 salcianu 1.1 @param methods methods where we look for allocation sites 264 salcianu 1.1 @param hcf code factory that provides the code of the methods 265 salcianu 1.1 266 salcianu 1.1 @return collection of all allocation sites (quads) from 267 salcianu 1.1 <code>methods</code> */ 268 salcianu 1.1 public static Collection getAllocs(Set methods, HCodeFactory hcf) { 269 salcianu 1.1 List allocs = new LinkedList(); 270 cananian 1.7 for(Object hmO : methods) { 271 cananian 1.7 HMethod hm = (HMethod) hmO; 272 salcianu 1.1 Code code = (Code) hcf.convert(hm); 273 salcianu 1.1 if(code != null) 274 salcianu 1.1 allocs.addAll(code.selectAllocations()); 275 salcianu 1.1 } 276 salcianu 1.1 return allocs; 277 salcianu 1.1 } 278 salcianu 1.1 }