Browse files

initial statistics implementation

  • Loading branch information...
1 parent a4bc026 commit 865d574c7bbcdcfbdf18508dd6fd724d906e1363 pret79 committed Sep 27, 2011
View
1 data/config.properties
@@ -68,7 +68,6 @@ update.generators.by.sound=true
### ### ### ### ###
# OUTPUT SETTINGS #
### ### ### ### ###
-fps.logging.enabled=true
statistics.enabled=true
# enable only ONE output device (pixelinvaders, rainbowduino, artnet or minidmx)
View
39 src/main/java/com/neophob/PixelController.java
@@ -20,17 +20,13 @@
package com.neophob;
import java.util.Properties;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;
import processing.core.PApplet;
import com.neophob.sematrix.glue.Collector;
import com.neophob.sematrix.glue.Shuffler;
-import com.neophob.sematrix.glue.Statistics;
import com.neophob.sematrix.output.ArtnetDevice;
import com.neophob.sematrix.output.Lpd6803Device;
import com.neophob.sematrix.output.MatrixEmulator;
@@ -42,6 +38,7 @@
import com.neophob.sematrix.output.emulatorhelper.InternalDebugWindow;
import com.neophob.sematrix.properties.ConfigConstant;
import com.neophob.sematrix.properties.PropertiesHelper;
+import com.neophob.sematrix.statistics.Statistics;
/**
* The Class PixelController.
@@ -65,10 +62,8 @@
/** The output. */
private Output output;
- // variables needed for logging
- private boolean fpsLoggingEnabled;
- private ScheduledExecutorService scheduledExecutorService;
- private int framesCounter;
+ private boolean statisticsEnabled;
+ private Statistics statistics;
/**
* prepare.
@@ -88,9 +83,10 @@ public void setup() {
PropertiesHelper ph = new PropertiesHelper(config);
// enable statistics logging
- Statistics statistics = Statistics.getInstance();
- if (ph.statisticsEnabled()) {
- statistics.enable();
+ this.statistics = Statistics.getInstance();
+ this.statisticsEnabled = ph.statisticsEnabled();
+ if (this.statisticsEnabled) {
+ this.statistics.enable();
}
Collector col = Collector.getInstance();
@@ -136,21 +132,6 @@ public void setup() {
col.setRandomMode(true);
}
- this.fpsLoggingEnabled = ph.isFPSLoggingEnabled();
- // enable average fps per minute logging
- if (this.fpsLoggingEnabled) {
- this.scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
- this.framesCounter = 0;
- Runnable fpsRunnable = new Runnable() {
- @Override
- public void run() {
- LOG.log(Level.INFO, "average fps per minute: {0}", framesCounter / 60f);
- framesCounter = 0;
- }
- };
- this.scheduledExecutorService.scheduleAtFixedRate(fpsRunnable, 60, 60, TimeUnit.SECONDS);
- }
-
LOG.log(Level.INFO,"--- PixelController Setup END ---");
}
@@ -162,10 +143,8 @@ public void draw() {
Collector.getInstance().updateSystem();
// log output statistics
this.output.logStatistics();
- // count average fps per minute if enabled
- if (this.fpsLoggingEnabled) {
- this.framesCounter++;
- }
+ // count average fps per minute
+ this.statistics.trackFPS(this.frameCount);
}
/**
View
5 src/main/java/com/neophob/sematrix/effect/PixelControllerEffect.java
@@ -33,9 +33,9 @@
import com.neophob.sematrix.effect.Effect.EffectName;
import com.neophob.sematrix.glue.Collector;
import com.neophob.sematrix.glue.PixelControllerElement;
-import com.neophob.sematrix.glue.Statistics;
import com.neophob.sematrix.glue.Visual;
import com.neophob.sematrix.properties.ValidCommands;
+import com.neophob.sematrix.statistics.Statistics;
/**
* The Class PixelControllerEffect.
@@ -74,6 +74,7 @@ public PixelControllerEffect() {
*/
@Override
public void update() {
+ long init = System.nanoTime();
// get a set with all active effects
Set<Integer> activeEffects = new HashSet<Integer>();
for (Visual visual : this.collector.getAllVisuals()) {
@@ -114,7 +115,7 @@ public void run() {
} catch (InterruptedException e) {
LOG.log(Level.SEVERE, "waiting for all effects to finish their update() method got interrupted!", e);
}
- this.statistics.sendEffectsUpdateTime(System.nanoTime() - start);
+ this.statistics.trackEffectsUpdateTime(init, start, System.nanoTime());
}
/**
View
5 src/main/java/com/neophob/sematrix/generator/PixelControllerGenerator.java
@@ -33,10 +33,10 @@
import com.neophob.sematrix.generator.Generator.GeneratorName;
import com.neophob.sematrix.glue.Collector;
import com.neophob.sematrix.glue.PixelControllerElement;
-import com.neophob.sematrix.glue.Statistics;
import com.neophob.sematrix.glue.Visual;
import com.neophob.sematrix.properties.PropertiesHelper;
import com.neophob.sematrix.properties.ValidCommands;
+import com.neophob.sematrix.statistics.Statistics;
/**
* The Class PixelControllerGenerator.
@@ -148,6 +148,7 @@ public void initAll() {
*/
@Override
public void update() {
+ long init = System.nanoTime();
// get a set with all active generators
Set<Integer> activeGenerators = new HashSet<Integer>();
for (Visual visual : this.collector.getAllVisuals()) {
@@ -188,7 +189,7 @@ public void run() {
} catch (InterruptedException e) {
LOG.log(Level.SEVERE, "waiting for all generators to finish their update() method got interrupted!", e);
}
- this.statistics.sendGeneratorsUpdateTime(System.nanoTime() - start);
+ this.statistics.trackGeneratorsUpdateTime(init, start, System.nanoTime());
}
/*
View
50 src/main/java/com/neophob/sematrix/glue/Statistics.java
@@ -1,50 +0,0 @@
-package com.neophob.sematrix.glue;
-
-
-public class Statistics {
- private boolean enabled;
-
- private Statistics() {
- this.enabled = false;
- }
-
- public synchronized void enable() {
- if (this.enabled) {
- throw new IllegalStateException("Statistics class can only be enabled once!");
- }
- this.enabled = true;
- }
-
- public boolean isEnabled() {
- return this.enabled;
- }
-
- private final static class StatisticsSingletonHolder {
- private final static Statistics INSTANCE = new Statistics();
- }
-
- public final static Statistics getInstance() {
- return StatisticsSingletonHolder.INSTANCE;
- }
-
- public void sendGeneratorsUpdateTime(long time) {
- if (!this.enabled) {
- return;
- // TODO implement statistics collection
- }
- }
-
- public void sendEffectsUpdateTime(long time) {
- if (!this.enabled) {
- return;
- }
- // TODO implement statistics collection
- }
-
- public void sendOutputsUpdateTime(long time) {
- if (!this.enabled) {
- return;
- }
- // TODO implement statistics collection
- }
-}
View
5 src/main/java/com/neophob/sematrix/output/PixelControllerOutput.java
@@ -29,7 +29,7 @@
import java.util.logging.Logger;
import com.neophob.sematrix.glue.PixelControllerElement;
-import com.neophob.sematrix.glue.Statistics;
+import com.neophob.sematrix.statistics.Statistics;
/**
* The Class PixelControllerOutput.
@@ -74,6 +74,7 @@ public void initAll() {
*/
@Override
public void update() {
+ long init = System.nanoTime();
final CountDownLatch startGate = new CountDownLatch(1);
final CountDownLatch endGate = new CountDownLatch(this.allOutputs.size());
for (final Output output: this.allOutputs) {
@@ -105,7 +106,7 @@ public void run() {
} catch (InterruptedException e) {
LOG.log(Level.SEVERE, "waiting for all outputs to finish their update() method got interrupted!", e);
}
- this.statistics.sendOutputsUpdateTime(System.nanoTime() - start);
+ this.statistics.trackOutputsUpdateTime(init, start, System.nanoTime());
}
/*
View
3 src/main/java/com/neophob/sematrix/properties/ConfigConstant.java
@@ -89,9 +89,6 @@ private ConfigConstant() {
public static final String DEBUG_WINDOW_MAX_X_SIZE = "maximal.debug.window.xsize";
- /** The Constant FPS_LOGGING_ENABLED. */
- public static final String FPS_LOGGING_ENABLED = "fps.logging.enabled";
-
/** The Constant STATISTICS_ENABLED. */
public static final String STATISTICS_ENABLED = "statistics.enabled";
}
View
4 src/main/java/com/neophob/sematrix/properties/PropertiesHelper.java
@@ -586,10 +586,6 @@ public int getDeviceYResolution() {
return deviceYResolution;
}
- public boolean isFPSLoggingEnabled() {
- return parseBoolean(ConfigConstant.FPS_LOGGING_ENABLED);
- }
-
public boolean statisticsEnabled() {
return parseBoolean(ConfigConstant.STATISTICS_ENABLED);
}
View
133 src/main/java/com/neophob/sematrix/statistics/Statistics.java
@@ -0,0 +1,133 @@
+package com.neophob.sematrix.statistics;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.commons.lang.time.DurationFormatUtils;
+
+
+public class Statistics {
+ private static final Logger LOG = Logger.getLogger(Statistics.class.getName());
+ private static final int LOGGING_INTERVAL = 60;
+
+ private boolean enabled;
+ private Map<ValueEnum, List<Long>> values;
+ private int frameCount;
+ private int referenceFrameCount;
+ private ScheduledExecutorService scheduledExecutorService;
+
+ private Statistics() {
+ this.enabled = false;
+ }
+
+ public synchronized void enable() {
+ if (this.enabled) {
+ throw new IllegalStateException("Statistics class can only be enabled once!");
+ }
+ // initialize class variables
+ this.enabled = true;
+ this.values = new ConcurrentHashMap<ValueEnum, List<Long>>();
+ for (ValueEnum valueEnum : ValueEnum.values()) {
+ this.values.put(valueEnum, new CopyOnWriteArrayList<Long>());
+ }
+ this.frameCount = 0;
+ this.referenceFrameCount = 0;
+ this.scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
+ // construct runnable instance
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ // calculate average values of all ValueEnum instances
+ long[] averageValues = new long[ValueEnum.values().length];
+ long[] totalValues = new long[ValueEnum.values().length];
+ for (ValueEnum valueEnum : ValueEnum.values()) {
+ averageValues[valueEnum.ordinal()] = 0;
+ for (Long value : values.get(valueEnum)) {
+ totalValues[valueEnum.ordinal()] += value;
+ }
+ averageValues[valueEnum.ordinal()] = totalValues[valueEnum.ordinal()] / values.get(valueEnum).size();
+ values.get(valueEnum).clear();
+ }
+ // calculate average fps per minute
+ float averageFPS = (frameCount - referenceFrameCount) / (float) LOGGING_INTERVAL;
+ referenceFrameCount = frameCount;
+ // log average values
+ StringBuffer stringBuffer = new StringBuffer();
+ for (ValueEnum valueEnum : ValueEnum.values()) {
+ // add average values
+ stringBuffer.append(valueEnum.getDescription());
+ stringBuffer.append(": ");
+ stringBuffer.append(DurationFormatUtils.formatDuration(
+ TimeUnit.MILLISECONDS.convert(averageValues[valueEnum.ordinal()], TimeUnit.NANOSECONDS),
+ "ss.SSS"
+ ));
+ stringBuffer.append("\n");
+ // add total values
+ stringBuffer.append(valueEnum.getDescription());
+ stringBuffer.append(" [total]");
+ stringBuffer.append(": ");
+ stringBuffer.append(DurationFormatUtils.formatDuration(
+ TimeUnit.MILLISECONDS.convert(totalValues[valueEnum.ordinal()], TimeUnit.NANOSECONDS),
+ "ss.SSS"
+ ));
+ stringBuffer.append("\n");
+ }
+ stringBuffer.append("average fps per minute: ");
+ stringBuffer.append(averageFPS);
+ LOG.log(Level.INFO, "##### statistic values of the last minute:\n" + stringBuffer.toString());
+ }
+ };
+ // schedule runnable
+ this.scheduledExecutorService.scheduleAtFixedRate(runnable, LOGGING_INTERVAL, LOGGING_INTERVAL, TimeUnit.SECONDS);
+ }
+
+ public boolean isEnabled() {
+ return this.enabled;
+ }
+
+ private final static class StatisticsSingletonHolder {
+ private final static Statistics INSTANCE = new Statistics();
+ }
+
+ public final static Statistics getInstance() {
+ return StatisticsSingletonHolder.INSTANCE;
+ }
+
+ public void trackGeneratorsUpdateTime(long init, long start, long end) {
+ if (!this.enabled) {
+ return;
+ }
+ this.values.get(ValueEnum.GENERATORS_UPDATE).add(end - init);
+ this.values.get(ValueEnum.GENERATORS_UPDATE_EFFECTIVE).add(end - start);
+ }
+
+ public void trackEffectsUpdateTime(long init, long start, long end) {
+ if (!this.enabled) {
+ return;
+ }
+ this.values.get(ValueEnum.EFFECTS_UPDATE).add(end - init);
+ this.values.get(ValueEnum.EFFECTS_UPDATE_EFFECTIVE).add(end - start);
+ }
+
+ public void trackOutputsUpdateTime(long init, long start, long end) {
+ if (!this.enabled) {
+ return;
+ }
+ this.values.get(ValueEnum.OUTPUTS_UPDATE).add(end - init);
+ this.values.get(ValueEnum.OUTPUTS_UPDATE_EFFECTIVE).add(end - start);
+ }
+
+ public void trackFPS(int frameCount) {
+ if (!this.enabled) {
+ return;
+ }
+ this.frameCount = frameCount;
+ }
+}
View
24 src/main/java/com/neophob/sematrix/statistics/ValueEnum.java
@@ -0,0 +1,24 @@
+package com.neophob.sematrix.statistics;
+
+import org.apache.commons.lang.Validate;
+
+public enum ValueEnum {
+ GENERATORS_UPDATE("average generators update duration"),
+ GENERATORS_UPDATE_EFFECTIVE("effective generators update duration"),
+ EFFECTS_UPDATE("average effects update duration"),
+ EFFECTS_UPDATE_EFFECTIVE("effective effects update duration"),
+ OUTPUTS_UPDATE("average outputs update duration"),
+ OUTPUTS_UPDATE_EFFECTIVE("effective outputs update duration");
+
+ private String description;
+
+ private ValueEnum(String description) {
+ Validate.notNull(description);
+ Validate.notEmpty(description);
+ this.description = description;
+ }
+
+ public String getDescription() {
+ return this.description;
+ }
+}

0 comments on commit 865d574

Please sign in to comment.