001: /*
002: * $Header: /cvs/j3d-contrib-utils/src/classes/org/jdesktop/j3d/utils/behaviors/PerfBehavior.java,v 1.3 2007/08/10 00:18:36 paulby Exp $
003: *
004: * Sun Public License Notice
005: *
006: * The contents of this file are subject to the Sun Public License Version
007: * 1.0 (the "License"). You may not use this file except in compliance with
008: * the License. A copy of the License is available at http://www.sun.com/
009: *
010: * The Original Code is Java 3D(tm) Fly Through.
011: * The Initial Developer of the Original Code is Paul Byrne.
012: * Portions created by Paul Byrne are Copyright (C) 2002.
013: * All Rights Reserved.
014: *
015: * Contributor(s): Paul Byrne.
016: *
017: **/
018: package org.jdesktop.j3d.utils.behaviors;
019:
020: import java.util.ArrayList;
021: import javax.media.j3d.*;
022: import javax.vecmath.*;
023:
024: /**
025: * A performance measurment behavior. The behavior automatically calibrates
026: * itself so that the work in measuring performance does not itself impact
027: * performance.
028: *
029: * Performance information will be passed to a registered PerfBehaviorListener,
030: * if there is no listener then the frames per second will be printed to
031: * System.out
032: *
033: * The org.jdesktop.j3dfly.utils.gui.StatsDialog class provides a
034: * GUI Dialog which uses this behavior to display performance stats.
035: *
036: * @author Chien Yang, Paul Byrne
037: * @version 1.9, 01/18/02
038: */
039: public class PerfBehavior extends Behavior {
040: WakeupOnElapsedFrames FPSwakeup = new WakeupOnElapsedFrames(0);
041: private int numFramesToDiscard = 8;
042:
043: private boolean doCalibration = true;
044: private int discardedFrames = 0;
045: private int numframes = 0;
046: private int maxframes = 1;
047: private long currtime = 0;
048: private long lasttime = 0;
049: private long deltatime;
050: private boolean finiteLoop = false;
051: private int loop = 0;
052: private int loopCount = 6;
053: private int testDuration = 1000;
054:
055: private ArrayList<PerfBehaviorListener> listeners;
056:
057: /**
058: * Construct the Behavior
059: * The Scheduling bounds are set to inifinity
060: */
061: public PerfBehavior() {
062: setSchedulingBounds(new BoundingSphere(new Point3d(0, 0, 0),
063: Double.POSITIVE_INFINITY));
064: setEnable(true);
065: }
066:
067: /**
068: * Print the fps results to System.out
069: */
070: public void printToSystemOut() {
071: addPerfBehaviorListener(new PerfBehaviorListener() {
072:
073: public void updatePerformanceFigures(float framesPerSecond) {
074: System.out.println("fps " + framesPerSecond);
075: }
076:
077: });
078: }
079:
080: public void calibrate() {
081: calibrate(8, 1000);
082: }
083:
084: /**
085: * Calibrate the behavior
086: */
087: public void calibrate(int framesToDiscard, int testDuration) {
088: doCalibration = true;
089: discardedFrames = 0;
090: numframes = 0;
091: maxframes = 1;
092: currtime = 0;
093: lasttime = 0;
094: loop = 0;
095: loopCount = 6;
096: this .testDuration = testDuration;
097: this .numFramesToDiscard = framesToDiscard;
098: }
099:
100: /**
101: * Called by Java3D to initialize the behavior
102: */
103: public void initialize() {
104: // Set the trigger for the interpolator
105: wakeupOn(FPSwakeup);
106: }
107:
108: /**
109: * Add the listener which will be notified whenever the performance
110: * stats are updated.
111: *
112: * Current implementation only supports a single listener
113: */
114: public void addPerfBehaviorListener(PerfBehaviorListener listener) {
115: if (listeners == null)
116: listeners = new ArrayList<PerfBehaviorListener>();
117: listeners.add(listener);
118: }
119:
120: /**
121: * Remove the PerfBehaviorListener
122: */
123: public void removePerfBehaviorListener(PerfBehaviorListener listener) {
124: if (listeners != null)
125: listeners.remove(listener);
126: }
127:
128: private void notifyListeners(float fps) {
129: for (PerfBehaviorListener l : listeners)
130: l.updatePerformanceFigures(fps);
131: }
132:
133: // Called every time the behavior is activated
134: public void processStimulus(java.util.Enumeration critera) {
135: // Apply Calibration Algorithm :
136: // To determine maxframes to run before sampling the time
137: // to determine frames per second.
138: // testduration = 10000 ,To run test pass for 10 seconds
139:
140: if (doCalibration) { // do the calibration
141: // Always throw away the next "N" frames *after* the first, dummy
142: // call to postSwap
143: if (discardedFrames <= numFramesToDiscard) {
144: if (false) {
145: if (discardedFrames == 0)
146: System.out
147: .println("postSwap: initial call discarded");
148: else
149: System.out.println("postSwap: frame #"
150: + discardedFrames + " discarded");
151: }
152:
153: discardedFrames += 1;
154: lasttime = currentTimeMillis();
155: } else {
156: numframes += 1;
157: //System.out.println(maxframes+" "+numframes+" "+lasttime+" ");
158: if (numframes >= maxframes) {
159: currtime = currentTimeMillis();
160: deltatime = currtime - lasttime;
161: // System.out.println("deltatime = " + deltatime +
162: // ", numframes = " + numframes);
163:
164: if (deltatime > testDuration && maxframes >= 8) {
165: maxframes = (int) Math.ceil((double) maxframes
166: * 1000 / (double) deltatime);
167: // System.out.println("maxframes = " + maxframes);
168:
169: // reset the value for the measurement
170: doCalibration = false;
171: numframes = 0;
172: lasttime = currentTimeMillis();
173: } else {
174: maxframes *= 2;
175: }
176: }
177: }
178: } else { // do the measurement
179: numframes += 1;
180: if (numframes >= maxframes) {
181: currtime = currentTimeMillis();
182: deltatime = currtime - lasttime;
183: double fps = (double) numframes
184: / ((double) deltatime / 1000.0d);
185: //System.out.println( numframes+" "+(deltatime/1000.0)+" "+fps);
186: if (listeners != null) {
187: notifyListeners((float) fps);
188: }
189: if (finiteLoop) {
190: loop++;
191: if (loop >= loopCount)
192: System.exit(0);
193: }
194: lasttime = currentTimeMillis();
195: numframes = 0;
196: }
197: }
198:
199: // Set the trigger for the interpolator
200: wakeupOn(FPSwakeup);
201:
202: }
203:
204: private long currentTimeMillis() {
205: return System.nanoTime() / 1000000;
206: }
207: }
|