/* * Copyright 2003-2012 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jetbrains.mps.typesystem; import org.jetbrains.mps.openapi.language.SAbstractConcept; import org.jetbrains.mps.openapi.model.SNode; import jetbrains.mps.util.Pair; import jetbrains.mps.util.performance.IPerformanceTracer; import java.util.*; import java.util.Map.Entry; public class TypeSystemReporter { private static TypeSystemReporter instance = null; private boolean isEnabled = false; private Map<String, Pair<Long, Long>> myGetTypeOfTime = new HashMap<String, Pair<Long, Long>>(); private Map<String, Pair<Long, Long>> myIsSubTypeTime = new HashMap<String, Pair<Long, Long>>(); private Map<String, Pair<Long, Long>> myCoerceTime = new HashMap<String, Pair<Long, Long>>(); private TypeSystemReporter() { } public static TypeSystemReporter getInstance() { if (instance == null) { instance = new TypeSystemReporter(); } return instance; } public void reset() { isEnabled = true; myGetTypeOfTime.clear(); myIsSubTypeTime.clear(); myCoerceTime.clear(); } public void reportTypeOf(SNode node, long time) { if (!isEnabled) return; String conceptFqName = node.getConcept().getQualifiedName(); report(time, conceptFqName, myGetTypeOfTime); } private void report(long time, String conceptFqName, Map<String, Pair<Long, Long>> map) { if (!isEnabled) return; Pair<Long, Long> value = map.get(conceptFqName); if (value == null) { value = new Pair<Long, Long>(0L, 0L); map.put(conceptFqName, value); } value.o1 += time; value.o2++; } public void reportIsSubType(SNode subType, SNode superType, long time) { if (!isEnabled || null == subType || null == superType) return; String conceptFqName = subType.getConcept().getQualifiedName() + " " + superType.getConcept().getQualifiedName(); report(time, conceptFqName, myIsSubTypeTime); } public void reportCoerce(SNode subType, SAbstractConcept concept, long time) { if (!isEnabled || null == subType) { return; } String conceptFqName = subType.getConcept().getQualifiedName() + " " + concept.getQualifiedName(); report(time, conceptFqName, myCoerceTime); } public void printReport(int numTop, IPerformanceTracer tracer) { tracer.addText("Time spent on getTypeOf operation"); printMapReport(myGetTypeOfTime, numTop, tracer); tracer.addText("Time spent on isSubType operation"); printMapReport(myIsSubTypeTime, numTop, tracer); tracer.addText("Time spent on coerce operation"); printMapReport(myCoerceTime, numTop, tracer); isEnabled = false; } public void printMapReport(Map<String, Pair<Long, Long>> map, int numTop, IPerformanceTracer tracer) { if (!isEnabled) return; ArrayList<Entry<String, Pair<Long, Long>>> list = new ArrayList<Entry<String, Pair<Long, Long>>>(); list.addAll(map.entrySet()); Collections.sort(list, new Comparator<Entry<String, Pair<Long, Long>>>() { @Override public int compare(Entry<String, Pair<Long, Long>> o1, Entry<String, Pair<Long, Long>> o2) { return o2.getValue().o1 > o1.getValue().o1 ? 1 : -1; } }); long sum = 0; int i = 0; for (Entry<String, Pair<Long, Long>> entry : list) { if (i++ >= numTop) break; sum += entry.getValue().o1; StringBuilder sb = new StringBuilder(); boolean isFirst = true; for (String name : entry.getKey().split(" ")) { if (!isFirst) { sb.append(" :< "); } isFirst = false; int beginIndex = name.lastIndexOf('.')+1; sb.append(name.substring(beginIndex)); } tracer.addText(String.format(sb.toString() + " %.3f s, %d times", entry.getValue().o1 * 1.0e-9, entry.getValue().o2)); } tracer.addText("Total: " + sum * 1.0e-9); } }