summaryrefslogtreecommitdiffstats
path: root/src/FPSCounter/FPSCounter.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/FPSCounter/FPSCounter.java')
-rw-r--r--src/FPSCounter/FPSCounter.java279
1 files changed, 279 insertions, 0 deletions
diff --git a/src/FPSCounter/FPSCounter.java b/src/FPSCounter/FPSCounter.java
new file mode 100644
index 0000000..a1d1d73
--- /dev/null
+++ b/src/FPSCounter/FPSCounter.java
@@ -0,0 +1,279 @@
+/*
+ * $RCSfile$
+ *
+ * Copyright (c) 2004 Sun Microsystems, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistribution of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any
+ * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
+ * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
+ * EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL
+ * NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF
+ * USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
+ * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR
+ * ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL,
+ * CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND
+ * REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF OR
+ * INABILITY TO USE THIS SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that this software is not designed, licensed or
+ * intended for use in the design, construction, operation or
+ * maintenance of any nuclear facility.
+ *
+ * $Revision$
+ * $Date$
+ * $State$
+ */
+
+import javax.media.j3d.*;
+import javax.vecmath.*;
+import java.text.*;
+
+/** This behavior calculates the frame rate and average frame rate of a
+ * Java3D application.
+ * The behavior sets itself up to wakeup every time a new frame is rendered.
+ *
+ * <p> The HotSpot(tm) compiler performs some initial optimizations before
+ * running at optimal speed. Frame rates measured during this warmup period
+ * will be inaccurate and not indicative of the true performance of the the
+ * application. Therefore, before beginning the frame rate computation,
+ * the frame counter waits for a fixed time period to allow the HotSpot(tm)
+ * compiler to stablilize.
+ *
+ * <p> To avoid computing the frame rate too frequently (which would also
+ * hamper rendering performance), the frame counter only computes the frame
+ * rate at fixed time intervals. The default sampling duration is 10 seconds.
+ * After waiting for the warmup period, the frame counter needs to calibrate
+ * itself. It computes the number of frames rendered during the sampling
+ * period. After doing this calibration, the frame counter reports the frame
+ * rate after these many frames are rendered. It also reports the average
+ * frame rate after a fixed number of sampling intervals (the default is 5).
+ *
+ * <p>The frame counter can be set up to run for a fixed number of sampling
+ * intervals or to run indefinitely. The defaultis to run indefinitely.
+ */
+
+public class FPSCounter extends Behavior {
+ // Wakeup condition - framecount = 0 -> wakeup on every frame
+ WakeupOnElapsedFrames FPSwakeup = new WakeupOnElapsedFrames(0);
+
+ // Do calibration for these many millisec
+ private static final long testduration = 1000;
+
+ // Report frame rate after every sampleduration milliseconds
+ private static final long sampleduration = 10000;
+
+ // Flag to indicate that it is time to (re)calibrate
+ private boolean doCalibration = true;
+
+ // Flag to indicate the counter has started
+ private boolean startup = true;
+
+ // Wait for HotSpot compiler to perform optimizations
+ private boolean warmup = true;
+
+ // Time to wait for HotSpot compiler to stabilize (in milliseconds)
+ private long warmupTime = 20000;
+
+ // Counter for number of frames rendered
+ private int numframes = 0;
+
+ // Report frame rate after maxframe number of frames have been rendered
+ private int maxframes = 1;
+
+ // Variables to keep track of elapsed time
+ private long startuptime = 0;
+ private long currtime = 0;
+ private long lasttime = 0;
+ private long deltatime;
+
+ // Run indefinitely or for a fixed duration
+ private boolean finiteLoop = false;
+
+ // No. of sampling intervals to run for if not running indefinitely
+ private long maxLoops;
+
+ // No. of sampling intervals run for so far
+ private long numLoops = 0;
+
+ // Total number of frames rendered so far
+ private int sumFrames = 0;
+
+ // Total time since last reporting of average frame rate
+ private long sumTimes = 0;
+
+ // Counts no. of sampling intervals
+ private int loop = 0;
+
+ // Average frame rate is reported after loopCount number of
+ // sampling intervals
+ private int loopCount = 5;
+ private double sumFps = 0.0;
+
+ private String symbol[] = {"\\", "|", "|", "/", "-", "|", "-"};
+ int index = 0;
+ private NumberFormat nf = null;
+
+ public FPSCounter() {
+ setEnable(true);
+ nf = NumberFormat.getNumberInstance();
+ }
+
+ /**
+ * Called to init the behavior
+ */
+ public void initialize() {
+ // Set the trigger for the behavior to wakeup on every frame rendered
+ wakeupOn(FPSwakeup);
+ }
+
+ /**
+ * Called every time the behavior is activated
+ */
+ public void processStimulus(java.util.Enumeration critera) {
+ // Apply calibration algorithm to determine number of frames to
+ // wait before computing frames per second.
+ // sampleduration = 10000 -> to run test, pass for 10 seconds.
+
+ if (doCalibration) { // start calibration
+ if (startup) {
+ // Record time at which the behavior was first invoked
+ startuptime = System.currentTimeMillis();
+ startup = false;
+ }
+ else if(warmup) { // Wait for the system to stabilize.
+ System.out.print("\rFPSCounter warming up..." +
+ symbol[(index++)%symbol.length]);
+ currtime = System.currentTimeMillis();
+ deltatime = currtime - startuptime;
+ if(deltatime > warmupTime) {
+ // Done waiting for warmup
+ warmup = false;
+ lasttime = System.currentTimeMillis();
+ System.out.println("\rFPSCounter warming up...Done");
+ }
+ }
+ else {
+ numframes += 1;
+ // Wait till at least maxframe no. of frames have been rendered
+ if (numframes >= maxframes) {
+ currtime = System.currentTimeMillis();
+ deltatime = currtime - lasttime;
+ // Do the calibration for testduration no. of millisecs
+ if (deltatime > testduration) {
+ // Compute total no. of frames rendered so far in the
+ // current sampling duration
+ maxframes = (int)Math.ceil((double)numframes *
+ ((double)sampleduration /
+ (double)deltatime));
+
+ // Done with calibration
+ doCalibration = false;
+ // reset the value for the measurement
+ numframes = 0;
+ lasttime = System.currentTimeMillis();
+ }
+ else {
+ // Need to run the calibration routine for some more
+ // time. Increase the no. of frames to be rendered
+ maxframes *= 2;
+ }
+ }
+ }
+ }
+ else { // do the measurement
+ numframes += 1;
+ if (numframes >= maxframes) {
+ currtime = System.currentTimeMillis();
+ deltatime = currtime - lasttime;
+ // time is in millisec, so multiply by 1000 to get frames/sec
+ double fps = (double)numframes / ((double)deltatime / 1000.0);
+
+ System.out.println("Frame Rate : \n\tNo. of frames : " +
+ numframes + "\n\tTime : " +
+ ((double)deltatime / 1000.0) +
+ " sec." + "\n\tFrames/sec : " + nf.format(fps));
+
+ // Calculate average frame rate
+ sumFrames += numframes;
+ sumTimes += deltatime;
+ sumFps += fps;
+ loop++;
+ if (loop >= loopCount) {
+ double avgFps = (double)sumFrames*1000.0/(double)sumTimes;
+ double ravgFps = sumFps/(double)loopCount;
+ System.out.println("Aggregate frame rate " +
+ nf.format(avgFps) + " frames/sec");
+ System.out.println("Average frame rate " +
+ nf.format(ravgFps) + " frames/sec");
+ numLoops++;
+ if (finiteLoop && numLoops >= maxLoops) {
+ System.out.println("************** The End **************\n");
+ setEnable(false);
+ }
+ loop = 0;
+ sumFps = 0;
+ }
+ numframes = 0;
+ lasttime = System.currentTimeMillis();;
+ }
+ }
+ // Set the trigger for the behavior
+ wakeupOn(FPSwakeup);
+ }
+
+ /**
+ * The frame counter waits for some time before computing the
+ * frame rate. This allows the HotSpot compiler to perform
+ * initial optimizations. The amount of time to wait for is set
+ * by this method. The default is 20000 (20 sec)
+ *
+ * @param amount of time to wait for before computing frame rate
+ * (specified in milliseconds)
+ */
+ public void setWarmupTime(long wt) {
+ warmupTime = wt;
+ }
+
+ /**
+ * Sets the number of sampling intervals to wait for before computing
+ * the average frame rate.
+ * The default is 5.
+ *
+ * @param number of sampling intervals over which to compute frame rate.
+ * A value of 0 implies the average frame rate is computed over one
+ * sampling interval
+ */
+ public void setLoopCount(int lc) {
+ loopCount = lc;
+ }
+
+ /**
+ * This method sets the number of sampling intervals for which
+ * the frame counter should run.
+ *
+ * @param number of sampling intervals to run for
+ */
+ public void setMaxLoops(int ml) {
+ maxLoops = ml;
+ finiteLoop = true;
+ }
+
+}