/*
* Copyright 2015 MovingBlocks
*
* 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 org.terasology.rendering.nui.layers.ingame.metrics;
import gnu.trove.map.TObjectDoubleMap;
import gnu.trove.procedure.TObjectDoubleProcedure;
import org.terasology.monitoring.PerformanceMonitor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
/**
* Like other MetricsMode implementations, an instance of this class will output a list of activities registered
* with the PerformanceMonitor and the execution time running means for each, in milliseconds.
* <br><br>
* Differently from other implementations, this class filters out all activities that are not prefixed
* with the strings "WorldRenderer::" and "PostProcessor::". Furthermore, it orders the activities alphabetically
* and poses no limit on the number of items displayed. Finally it places the time value on the left, making an
* attempt to align the digits, while the name of the associated activity is on the right, after a separator.
*/
public class RenderingExecTimeMeansMode extends MetricsMode {
private StringBuilder builder = new StringBuilder();
private ArrayList<MetricsEntry> processedEntries = new ArrayList<>();
private AlphabeticalAscendingComparator inAscendingAlphabeticalOrder = new AlphabeticalAscendingComparator();
private TObjectDoubleProcedure<String> matchingCriteria = new FilterByStartWith();
private EntryAdder addEntryToProcessedEntries = new EntryAdder();
public RenderingExecTimeMeansMode(String name) {
super(name);
}
@Override
public String getMetrics() {
builder.setLength(0);
builder.append(getName());
builder.append("\n");
processMetrics(PerformanceMonitor.getRunningMean());
return builder.toString();
}
private void processMetrics(TObjectDoubleMap<String> activitiesToMetricsMap) {
activitiesToMetricsMap.retainEntries(matchingCriteria);
processedEntries.clear();
activitiesToMetricsMap.forEachEntry(addEntryToProcessedEntries);
Collections.sort(processedEntries, inAscendingAlphabeticalOrder);
for (MetricsEntry entry : processedEntries) {
builder.append(String.format("%,10.2f", entry.metricsValue));
builder.append("ms - ");
builder.append(entry.activityName);
builder.append("\n");
}
}
@Override
public boolean isAvailable() {
return true;
}
@Override
public boolean isPerformanceManagerMode() {
return true;
}
private class FilterByStartWith implements TObjectDoubleProcedure<String> {
@Override
public boolean execute(String activityName, double metricsValue) {
return activityName.startsWith("WorldRenderer::") || activityName.startsWith("PostProcessor::");
}
}
private class MetricsEntry {
public String activityName;
public double metricsValue;
MetricsEntry(String activityName, double metricsValue) {
this.activityName = activityName;
this.metricsValue = metricsValue;
}
}
private class EntryAdder implements TObjectDoubleProcedure<String> {
@Override
public boolean execute(String activityName, double metricsValue) {
processedEntries.add(new MetricsEntry(activityName, metricsValue));
return true;
}
}
private static class AlphabeticalAscendingComparator implements Comparator<MetricsEntry> {
@Override
public int compare(MetricsEntry firstEntry, MetricsEntry secondEntry) {
return firstEntry.activityName.compareTo(secondEntry.activityName);
}
}
}