package edu.brown.hstore.stats; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.TreeSet; import org.apache.log4j.Logger; import org.voltdb.StatsSource; import org.voltdb.SysProcSelector; import org.voltdb.VoltTable; import org.voltdb.VoltTable.ColumnInfo; import org.voltdb.VoltType; import org.voltdb.types.SpeculationType; import org.voltdb.utils.Pair; import edu.brown.hstore.HStoreSite; import edu.brown.hstore.PartitionExecutor; import edu.brown.hstore.SpecExecScheduler; import edu.brown.logging.LoggerUtil; import edu.brown.logging.LoggerUtil.LoggerBoolean; import edu.brown.profilers.ProfileMeasurement; import edu.brown.profilers.SpecExecProfiler; import edu.brown.statistics.HistogramUtil; import edu.brown.utils.MathUtil; /** * Stats Source for SpecExecProfiler * @author pavlo */ public class SpecExecProfilerStats extends StatsSource { private static final Logger LOG = Logger.getLogger(SpecExecProfilerStats.class); private static final LoggerBoolean debug = new LoggerBoolean(); static { LoggerUtil.attachObserver(LOG, debug); } private final HStoreSite hstore_site; /** * PartitionId+SpeculationType */ private Set<Pair<Integer, SpeculationType>> sortedPair = new TreeSet<Pair<Integer,SpeculationType>>(); public SpecExecProfilerStats(HStoreSite hstore_site) { super(SysProcSelector.SPECEXECPROFILER.name(), false); this.hstore_site = hstore_site; for (int partition: hstore_site.getLocalPartitionIds().values()) { for (SpeculationType type: SpeculationType.values()) { if (type != SpeculationType.NULL) { Pair<Integer, SpeculationType> pair = new Pair<Integer, SpeculationType>(partition, type); this.sortedPair.add(pair); } } // FOR } // FOR } @Override protected Iterator<Object> getStatsRowKeyIterator(boolean interval) { //final Iterator<Integer> it = hstore_site.getLocalPartitionIds().iterator(); final Iterator<Pair<Integer,SpeculationType>> it = sortedPair.iterator(); return new Iterator<Object>() { @Override public boolean hasNext() { return it.hasNext(); } @Override public Object next() { return it.next(); } @Override public void remove() { it.remove(); } }; } @Override protected void populateColumnSchema(ArrayList<ColumnInfo> columns) { super.populateColumnSchema(columns); columns.add(new VoltTable.ColumnInfo("PARTITION", VoltType.INTEGER)); columns.add(new VoltTable.ColumnInfo("SPECULATE_TYPE", VoltType.STRING)); columns.add(new VoltTable.ColumnInfo("SUCCESS_CNT", VoltType.BIGINT)); columns.add(new VoltTable.ColumnInfo("SUCCESS_RATE", VoltType.FLOAT)); columns.add(new VoltTable.ColumnInfo("INTERRUPT_CNT", VoltType.BIGINT)); columns.add(new VoltTable.ColumnInfo("INTERRUPT_RATE", VoltType.FLOAT)); columns.add(new VoltTable.ColumnInfo("QUEUE_SIZE_AVG", VoltType.BIGINT)); columns.add(new VoltTable.ColumnInfo("QUEUE_SIZE_STDEV", VoltType.FLOAT)); columns.add(new VoltTable.ColumnInfo("COMPARISONS_AVG", VoltType.BIGINT)); columns.add(new VoltTable.ColumnInfo("COMPARISONS_STDEV", VoltType.FLOAT)); columns.add(new VoltTable.ColumnInfo("MATCHES_AVG", VoltType.BIGINT)); columns.add(new VoltTable.ColumnInfo("MATCHES_STDEV", VoltType.FLOAT)); columns.add(new VoltTable.ColumnInfo("EXECUTED_PER_TXN_AVG", VoltType.BIGINT)); columns.add(new VoltTable.ColumnInfo("EXECUTED_PER_TXN_STDEV", VoltType.FLOAT)); // Make a dummy profiler just so that we can get the fields from it SpecExecProfiler profiler = new SpecExecProfiler(); for (ProfileMeasurement pm : profiler.getProfileMeasurements()) { String name = pm.getName().toUpperCase(); // We need two columns per ProfileMeasurement // (1) The total think time in nanoseconds // (2) The number of invocations columns.add(new VoltTable.ColumnInfo(name, VoltType.BIGINT)); columns.add(new VoltTable.ColumnInfo(name+"_CNT", VoltType.BIGINT)); columns.add(new VoltTable.ColumnInfo(name+"_STDEV", VoltType.FLOAT)); } // FOR } @Override protected synchronized void updateStatsRow(Object rowKey, Object[] rowValues) { @SuppressWarnings("unchecked") Pair<Integer, SpeculationType> rowKeyPair = (Pair<Integer, SpeculationType>) rowKey; Integer partition = rowKeyPair.getFirst(); SpeculationType specType = rowKeyPair.getSecond(); PartitionExecutor.Debug executorDebug = hstore_site.getPartitionExecutor(partition).getDebugContext(); SpecExecScheduler.Debug specExecDebug = executorDebug.getSpecExecScheduler().getDebugContext(); SpecExecProfiler profiler = specExecDebug.getProfiler(specType); assert(profiler != null); int offset = columnNameToIndex.get("PARTITION"); double total = (double)profiler.total_time.getInvocations(); rowValues[offset++] = partition; rowValues[offset++] = specType.toString(); rowValues[offset++] = profiler.success; rowValues[offset++] = profiler.success / total; rowValues[offset++] = profiler.interrupts; rowValues[offset++] = profiler.interrupts / total; rowValues[offset++] = MathUtil.weightedMean(profiler.queue_size); rowValues[offset++] = HistogramUtil.stdev(profiler.queue_size); rowValues[offset++] = MathUtil.weightedMean(profiler.num_comparisons); rowValues[offset++] = HistogramUtil.stdev(profiler.num_comparisons); rowValues[offset++] = MathUtil.weightedMean(profiler.num_matches); rowValues[offset++] = HistogramUtil.stdev(profiler.num_matches); rowValues[offset++] = MathUtil.weightedMean(profiler.num_executed); rowValues[offset++] = HistogramUtil.stdev(profiler.num_executed); List<Long> history = new ArrayList<Long>(); for (ProfileMeasurement pm : profiler.getProfileMeasurements()) { rowValues[offset++] = pm.getTotalThinkTime(); rowValues[offset++] = pm.getInvocations(); rowValues[offset++] = MathUtil.stdev(pm.getHistory(history)); history.clear(); } // FOR super.updateStatsRow(rowKey, rowValues); } }