Java tutorial
/* * TURNUS, the co-exploration framework * * Copyright (C) 2014 EPFL SCI STI MM * * This file is part of TURNUS. * * TURNUS is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * TURNUS is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with TURNUS. If not, see <http://www.gnu.org/licenses/>. * * Additional permission under GNU GPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or combining it * with Eclipse (or a modified version of Eclipse or an Eclipse plugin or * an Eclipse library), containing parts covered by the terms of the * Eclipse Public License (EPL), the licensors of this Program grant you * additional permission to convey the resulting work. Corresponding Source * for a non-source form of such a combination shall include the source code * for the parts of Eclipse libraries used as well as that of the covered work. * */ package co.turnus.analysis.bottlenecks.util; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.apache.commons.collections.map.LinkedMap; import co.turnus.analysis.data.bottlenecks.ActionHotspotsData; import co.turnus.analysis.data.bottlenecks.AlgoBottlenecksData; import co.turnus.analysis.data.bottlenecks.ExecData; import co.turnus.analysis.data.bottlenecks.ExtendExecData; import co.turnus.analysis.data.bottlenecks.HotspotsData; import co.turnus.analysis.data.util.DataUtil; import co.turnus.dataflow.Action; import co.turnus.dataflow.Actor; import co.turnus.dataflow.ActorClass; import co.turnus.dataflow.Network; import co.turnus.dataflow.util.DataflowComparators; import com.google.common.collect.HashBasedTable; import com.google.common.collect.ImmutableTable; import com.google.common.collect.Maps; import com.google.common.collect.Ordering; import com.google.common.collect.Sets; import com.google.common.collect.Table; import com.google.common.collect.Table.Cell; public class HotspotsDataAnalyser { private class ActionDataComparator implements Comparator<ActionHotspotsData> { private Key key; private Order order; private ExecDataComparator subComparator = new ExecDataComparator(); @Override public int compare(ActionHotspotsData o1, ActionHotspotsData o2) { if (o1 == null && o2 == null) { return 0; } else if (o1 == null) { return 1; } else if (o2 == null) { return -1; } switch (key) { case ALPHABETICAL: { int val = DataflowComparators.action(false).compare(o1.getAction(), o2.getAction()); return order == Order.INCREASING ? val : -val; } case TOTAL_EXECUTIONS: case TOTAL_VARIANCE: case TOTAL_CLOCKCYCLES: { ExecData d1 = o1.getTotalExec(); ExecData d2 = o2.getTotalExec(); return subComparator.compare(d1, d2); } case NOTDEFERRABLE_EXECUTIONS: case NOTDEFERRABLE_VARIANCE: case NOTDEFERRABLE_CLOCKCYCLES: { ExecData d1 = o1.getNotDeferrableExec(); ExecData d2 = o2.getNotDeferrableExec(); return subComparator.compare(d1, d2); } case CRITICAL_EXECUTIONS: case CRITICAL_VARIANCE: case CRITICAL_CLOCKCYCLES: { ExecData d1 = o1.getCriticalExec(); ExecData d2 = o2.getCriticalExec(); return subComparator.compare(d1, d2); } default: return 0; } } private void setDirection(Key key, Order order) { this.key = key; this.order = order; subComparator.setSorting(key, order); } } private class ExecDataComparator implements Comparator<ExecData> { private Key key; private Order order; @Override public int compare(ExecData o1, ExecData o2) { if (o1 == null && o2 == null) { return 0; } else if (o1 == null) { return 1; } else if (o2 == null) { return -1; } switch (key) { case TOTAL_EXECUTIONS: case CRITICAL_EXECUTIONS: case NOTDEFERRABLE_EXECUTIONS: { long d1 = o1.getExecutions(); long d2 = o2.getExecutions(); int val = Long.compare(d1, d2); return order == Order.INCREASING ? val : -val; } case TOTAL_VARIANCE: case NOTDEFERRABLE_VARIANCE: case CRITICAL_VARIANCE: { double d1 = o1.getClockCyclesVariance(); double d2 = o2.getClockCyclesVariance(); int val = Double.compare(d1, d2); return order == Order.INCREASING ? val : -val; } case TOTAL_CLOCKCYCLES: case NOTDEFERRABLE_CLOCKCYCLES: case CRITICAL_CLOCKCYCLES: { double d1 = o1.getClockCyclesMean(); double d2 = o2.getClockCyclesMean(); int val = Double.compare(d1, d2); return order == Order.INCREASING ? val : -val; } default: return 0; } } private void setSorting(Key key, Order order) { this.key = key; this.order = order; } } private class ExecDataMapComparator implements Comparator<Map.Entry<?, ExtendExecData>> { private Key key; private Order order; private ExecDataComparator subComparator = new ExecDataComparator(); @Override public int compare(Entry<?, ExtendExecData> o1, Entry<?, ExtendExecData> o2) { if (o1 == null && o2 == null) { return 0; } else if (o1 == null) { return 1; } else if (o2 == null) { return -1; } switch (key) { case ALPHABETICAL: { int val = 0; if (o1.getKey() instanceof Actor) { val = DataflowComparators.actor(false).compare((Actor) o1.getKey(), (Actor) o2.getKey()); } else if (o1.getKey() instanceof ActorClass) { val = DataflowComparators.actorClass(false).compare((ActorClass) o1.getKey(), (ActorClass) o2.getKey()); } else if (o1.getKey() instanceof Action) { val = DataflowComparators.action(false).compare((Action) o1.getKey(), (Action) o2.getKey()); } else { return val; } return order == Order.INCREASING ? val : -val; } case TOTAL_EXECUTIONS: case TOTAL_VARIANCE: case TOTAL_CLOCKCYCLES: { ExecData d1 = o1.getValue().getTotalExec(); ExecData d2 = o2.getValue().getTotalExec(); return subComparator.compare(d1, d2); } case NOTDEFERRABLE_EXECUTIONS: case NOTDEFERRABLE_VARIANCE: case NOTDEFERRABLE_CLOCKCYCLES: { ExecData d1 = o1.getValue().getNotDeferrableExec(); ExecData d2 = o2.getValue().getNotDeferrableExec(); return subComparator.compare(d1, d2); } case CRITICAL_EXECUTIONS: case CRITICAL_VARIANCE: case CRITICAL_CLOCKCYCLES: { ExecData d1 = o1.getValue().getCriticalExec(); ExecData d2 = o2.getValue().getCriticalExec(); return subComparator.compare(d1, d2); } default: return 0; } } private void setSorting(Key key, Order order) { subComparator.setSorting(key, order); this.key = key; this.order = order; } } private class ExecDataTableComparator extends Ordering<Table.Cell<?, Action, ExtendExecData>> { private Key key; private Order order; private ExecDataComparator subComparator = new ExecDataComparator(); @Override public int compare(Cell<?, Action, ExtendExecData> o1, Cell<?, Action, ExtendExecData> o2) { if (o1 == null && o2 == null) { return 0; } else if (o1 == null) { return 1; } else if (o2 == null) { return -1; } switch (key) { case ALPHABETICAL: { int val = 0; if (o1.getRowKey() instanceof Actor) { val = DataflowComparators.actor(false).compare((Actor) o1.getRowKey(), (Actor) o2.getRowKey()); } else if (o1.getRowKey() instanceof ActorClass) { val = DataflowComparators.actorClass(false).compare((ActorClass) o1.getRowKey(), (ActorClass) o2.getRowKey()); } else { return val; } return order == Order.INCREASING ? val : -val; } case TOTAL_EXECUTIONS: case TOTAL_VARIANCE: case TOTAL_CLOCKCYCLES: { ExecData d1 = o1.getValue().getTotalExec(); ExecData d2 = o2.getValue().getTotalExec(); return subComparator.compare(d1, d2); } case NOTDEFERRABLE_EXECUTIONS: case NOTDEFERRABLE_VARIANCE: case NOTDEFERRABLE_CLOCKCYCLES: { ExecData d1 = o1.getValue().getNotDeferrableExec(); ExecData d2 = o2.getValue().getNotDeferrableExec(); return subComparator.compare(d1, d2); } case CRITICAL_EXECUTIONS: case CRITICAL_VARIANCE: case CRITICAL_CLOCKCYCLES: { ExecData d1 = o1.getValue().getCriticalExec(); ExecData d2 = o2.getValue().getCriticalExec(); return subComparator.compare(d1, d2); } default: return 0; } } private void setSorting(Key key, Order order) { subComparator.setSorting(key, order); this.key = key; this.order = order; } } public enum Key { /** */ ALPHABETICAL, /** */ TOTAL_EXECUTIONS, /** */ TOTAL_CLOCKCYCLES, /** */ TOTAL_VARIANCE, /** */ NOTDEFERRABLE_EXECUTIONS, /** */ NOTDEFERRABLE_CLOCKCYCLES, /** */ NOTDEFERRABLE_VARIANCE, /** */ CRITICAL_EXECUTIONS, /** */ CRITICAL_CLOCKCYCLES, /** */ CRITICAL_VARIANCE; } public enum Order { /** */ DECREASING, /** */ INCREASING; } private HotspotsData data; private Network network; private ActionDataComparator listComparator; private ExecDataTableComparator tableComparator; private ExecDataMapComparator mapComparator; public HotspotsDataAnalyser(AlgoBottlenecksData data) { this.data = data.getHotspotsData(); this.network = data.getNetwork(); listComparator = new ActionDataComparator(); tableComparator = new ExecDataTableComparator(); mapComparator = new ExecDataMapComparator(); } public ActionHotspotsData getData(Actor actor, Action action) { for (ActionHotspotsData aData : data.getActionsData()) { if (aData.getActor().equals(actor) && aData.getAction().equals(action)) return aData; } return null; } public List<ActionHotspotsData> getSortedData(Action action, Key key, Order order) { ArrayList<ActionHotspotsData> list = new ArrayList<>(); for (ActionHotspotsData aData : data.getActionsData()) { if (aData.getAction().equals(action)) list.add(aData); } sortList(list, key, order); return list; } public List<ActionHotspotsData> getSortedData(Actor actor, Key key, Order order) { ArrayList<ActionHotspotsData> list = new ArrayList<>(); for (ActionHotspotsData aData : data.getActionsData()) { if (aData.getActor().equals(actor)) list.add(aData); } sortList(list, key, order); return list; } public List<ActionHotspotsData> getSortedData(ActorClass actorClass, Key key, Order order) { ArrayList<ActionHotspotsData> list = new ArrayList<>(); for (ActionHotspotsData aData : data.getActionsData()) { if (aData.getActor().getActorClass().equals(actorClass)) list.add(aData); } sortList(list, key, order); return list; } public List<ActionHotspotsData> getSortedData(Key key, Order order) { ArrayList<ActionHotspotsData> list = new ArrayList<>(data.getActionsData()); sortList(list, key, order); return list; } public ExtendExecData getSumData() { List<ActionHotspotsData> list = data.getActionsData(); return DataUtil.sum(list.toArray(new ExtendExecData[list.size()])); } public ExtendExecData getSumData(Action action) { List<ActionHotspotsData> list = new ArrayList<ActionHotspotsData>(); for (ActionHotspotsData actionData : data.getActionsData()) { if (actionData.getAction().equals(action)) { list.add(actionData); } } return DataUtil.sum(list.toArray(new ExtendExecData[list.size()])); } public ExtendExecData getSumData(Actor actor) { List<ActionHotspotsData> list = new ArrayList<ActionHotspotsData>(); for (ActionHotspotsData actionData : data.getActionsData()) { if (actionData.getActor().equals(actor)) { list.add(actionData); } } return DataUtil.sum(list.toArray(new ExtendExecData[list.size()])); } public ExtendExecData getSumData(ActorClass actorClass) { List<ActionHotspotsData> list = new ArrayList<ActionHotspotsData>(); for (ActionHotspotsData actionData : data.getActionsData()) { if (actionData.getActor().getActorClass().equals(actorClass)) { list.add(actionData); } } return DataUtil.sum(list.toArray(new ExtendExecData[list.size()])); } @SuppressWarnings("unchecked") public <T> Map<T, ExtendExecData> getSumDataMap(Class<T> type, Key key, Order order) { Map<T, ExtendExecData> tmpMap = Maps.newHashMap(); List<Map.Entry<T, ExtendExecData>> list = new ArrayList<>(); if (type.isAssignableFrom(Actor.class)) { for (Actor actor : network.getActors()) { tmpMap.put((T) actor, getSumData(actor)); } list.addAll(tmpMap.entrySet()); } else if (type.isAssignableFrom(ActorClass.class)) { for (ActorClass clazz : network.getActorClasses()) { tmpMap.put((T) clazz, getSumData(clazz)); } list.addAll(tmpMap.entrySet()); } else if (type.isAssignableFrom(Action.class)) { Collection<Action> actions = Sets.newHashSet(); for (ActorClass clazz : network.getActorClasses()) { actions.addAll(clazz.getActions()); } for (Action action : actions) { tmpMap.put((T) action, getSumData(action)); } list.addAll(tmpMap.entrySet()); } else { return null; } mapComparator.setSorting(key, order); Collections.sort(list, mapComparator); Map<T, ExtendExecData> data = new LinkedMap(); for (Entry<T, ExtendExecData> entry : list) { data.put(entry.getKey(), entry.getValue()); } return data; } @SuppressWarnings("unchecked") public <T> Table<T, Action, ExtendExecData> getSumDataTable(Class<T> type, Key key, Order order) { if (type.isAssignableFrom(Actor.class)) { // create a temporary table Table<Actor, Action, ExtendExecData> table = HashBasedTable.create(); for (ActionHotspotsData aData : data.getActionsData()) { table.put(aData.getActor(), aData.getAction(), aData); } // sort the table tableComparator.setSorting(key, order); ImmutableTable.Builder<Actor, Action, ExtendExecData> sortedBuilder = ImmutableTable.builder(); // preserves insertion order for (Table.Cell<Actor, Action, ExtendExecData> cell : tableComparator.sortedCopy(table.cellSet())) { sortedBuilder.put(cell); } // return a sorted table return (Table<T, Action, ExtendExecData>) sortedBuilder.build(); } else if (type.isAssignableFrom(ActorClass.class)) { // create a temporary table Table<ActorClass, Action, ExtendExecData> table = HashBasedTable.create(); for (ActionHotspotsData aData : data.getActionsData()) { ActorClass clazz = aData.getActor().getActorClass(); Action action = aData.getAction(); ExtendExecData actionData = table.get(clazz, action); if (actionData == null) { actionData = aData; table.put(clazz, action, actionData); } else { DataUtil.merge(actionData, aData); } } // sort the table tableComparator.setSorting(key, order); ImmutableTable.Builder<ActorClass, Action, ExtendExecData> sortedBuilder = ImmutableTable.builder(); // preserves insertion order for (Table.Cell<ActorClass, Action, ExtendExecData> cell : tableComparator .sortedCopy(table.cellSet())) { sortedBuilder.put(cell); } // return a sorted table return (Table<T, Action, ExtendExecData>) sortedBuilder.build(); } return null; } private void sortList(ArrayList<ActionHotspotsData> list, Key key, Order order) { listComparator.setDirection(key, order); Collections.sort(list, listComparator); } }