diff --git a/README.md b/README.md index 1d0dba9..1ffd1b1 100644 --- a/README.md +++ b/README.md @@ -3,55 +3,28 @@ stats.as #### Actionscript Performance Monitor #### -![stats_as.png](http://github.com/mrdoob/stats.as/raw/master/assets/stats_as.png) +[![Flattr this](http://api.flattr.com/button/button-compact-static-100x17.png)](http://flattr.com/thing/20491/stats-as) This class provides a simple info box that will help you monitor your code performance. -* FPS Frames per second, how many frames were rendered in 1 second. The higher the number, the better. -* MS Milliseconds needed to render a frame. The lower number, the better. -* MEM Memory your code is using, if it increases per frame is VERY wrong. -* MAX Maximum memory the application reached. +* **FPS** Frames per second, how many frames were rendered in 1 second. The higher the number the better. +* **MS** Milliseconds needed to render a frame. The lower the number the better. +* **MEM** Memory your code is using, if it increases per frame is VERY wrong. +* **MAX** Maximum memory the application reached. + +### Screenshot ### -### How to use ### +![stats_as.png](http://github.com/mrdoob/stats.as/raw/master/assets/stats_as.png) + +### Usage ### addChild( new Stats() ); ### Controls ### -* **LEFT CLICK** on the top-half/bottom-half part of the panel to increase/decrease the movie FPS limit. +* **CLICK** Top-half / bottom-half part of the panel to increase/decrease the FPS of the application. ### Download ### -[Stats.as](http://github.com/mrdoob/stats.as/raw/master/src/net/hires/debug/Stats.as) - -### Change Log ### - -2009 10 22 - v**2.2** - -* FlipX of graph to be more logic. -* Destroy on Event.REMOVED_FROM_STAGE (thx joshtynjala) - - -2009 03 28 - v**2.1** - -* Theme support. - - -2009 02 21 - v**2.0** - -* changed text system -* added MAX value (Max memory reached). very useful for spotting memory leaks -* removed player version on roll over (let me know if this is a bad idea) -* simplified - - -2009 02 07 - v**1.5** - -* onRemovedFromStage() (thx huihuicn.xu) - - -2008 12 14 - v**1.4** - -* Code optimisations, should take even less CPU -* Fixed ugly drawing when transparent (thx makc.the.great) -* Added Version info on Mouse Over. +[Stats.as](http://github.com/mrdoob/stats.as/raw/master/src/net/hires/debug/Stats.as) +[Stats.hx](http://github.com/mrdoob/stats.as/raw/master/src/net/hires/debug/Stats.hx) (Ported by [David Wilhelm](http://github.com/bigfish)) diff --git a/assets/stats_as.png b/assets/stats_as.png index a72cc09..5a91438 100644 Binary files a/assets/stats_as.png and b/assets/stats_as.png differ diff --git a/src/net/hires/debug/Stats.as b/src/net/hires/debug/Stats.as index 29c65ed..509a083 100644 --- a/src/net/hires/debug/Stats.as +++ b/src/net/hires/debug/Stats.as @@ -11,24 +11,24 @@ * **/ -package net.hires.debug -{ - import flash.display.Bitmap; +package net.hires.debug { + import flash.display.BitmapData; import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; + import flash.geom.Matrix; import flash.geom.Rectangle; import flash.system.System; import flash.text.StyleSheet; import flash.text.TextField; import flash.utils.getTimer; - public class Stats extends Sprite - { + public class Stats extends Sprite { + protected const WIDTH : uint = 70; protected const HEIGHT : uint = 100; - + protected var xml : XML; protected var text : TextField; @@ -40,42 +40,31 @@ package net.hires.debug protected var ms_prev : uint; protected var mem : Number; protected var mem_max : Number; - - protected var graph : Bitmap; + + protected var graph : BitmapData; protected var rectangle : Rectangle; - + protected var fps_graph : uint; protected var mem_graph : uint; protected var mem_max_graph : uint; - - protected var theme : Object = { bg: 0x000033, fps: 0xffff00, ms: 0x00ff00, mem: 0x00ffff, memmax: 0xff0070 }; + + protected var colors : Colors = new Colors(); /** * Stats FPS, MS and MEM, all in one. - * - * @param _theme Example: { bg: 0x202020, fps: 0xC0C0C0, ms: 0x505050, mem: 0x707070, memmax: 0xA0A0A0 } */ - public function Stats( _theme : Object = null ) : void - { - if (_theme) - { - if (_theme.bg != null) theme.bg = _theme.bg; - if (_theme.fps != null) theme.fps = _theme.fps; - if (_theme.ms != null) theme.ms = _theme.ms; - if (_theme.mem != null) theme.mem = _theme.mem; - if (_theme.memmax != null) theme.memmax = _theme.memmax; - } + public function Stats() : void { mem_max = 0; xml = FPS:MS:MEM:MAX:; style = new StyleSheet(); - style.setStyle("xml", {fontSize:'9px', fontFamily:'_sans', leading:'-2px'}); - style.setStyle("fps", {color: hex2css(theme.fps)}); - style.setStyle("ms", {color: hex2css(theme.ms)}); - style.setStyle("mem", {color: hex2css(theme.mem)}); - style.setStyle("memMax", {color: hex2css(theme.memmax)}); + style.setStyle('xml', {fontSize:'9px', fontFamily:'_sans', leading:'-2px'}); + style.setStyle('fps', {color: hex2css(colors.fps)}); + style.setStyle('ms', {color: hex2css(colors.ms)}); + style.setStyle('mem', {color: hex2css(colors.mem)}); + style.setStyle('memMax', {color: hex2css(colors.memmax)}); text = new TextField(); text.width = WIDTH; @@ -85,70 +74,72 @@ package net.hires.debug text.selectable = false; text.mouseEnabled = false; - graph = new Bitmap(); - graph.y = 50; - - rectangle = new Rectangle( WIDTH - 1, 0, 1, HEIGHT - 50 ); + rectangle = new Rectangle(WIDTH - 1, 0, 1, HEIGHT - 50); addEventListener(Event.ADDED_TO_STAGE, init, false, 0, true); addEventListener(Event.REMOVED_FROM_STAGE, destroy, false, 0, true); + } - private function init(e : Event) : void - { - graphics.beginFill(theme.bg); + private function init(e : Event) : void { + + graphics.beginFill(colors.bg); graphics.drawRect(0, 0, WIDTH, HEIGHT); graphics.endFill(); addChild(text); - graph.bitmapData = new BitmapData(WIDTH, HEIGHT - 50, false, theme.bg); - addChild(graph); + graph = new BitmapData(WIDTH, HEIGHT - 50, false, colors.bg); + graphics.beginBitmapFill(graph, new Matrix(1, 0, 0, 1, 0, 50)); + graphics.drawRect(0, 50, WIDTH, HEIGHT - 50); addEventListener(MouseEvent.CLICK, onClick); addEventListener(Event.ENTER_FRAME, update); + } - - private function destroy(e : Event) : void - { + + private function destroy(e : Event) : void { + graphics.clear(); while(numChildren > 0) removeChildAt(0); - graph.bitmapData.dispose(); + graph.dispose(); removeEventListener(MouseEvent.CLICK, onClick); removeEventListener(Event.ENTER_FRAME, update); - } + + } - private function update(e : Event) : void - { + private function update(e : Event) : void { + timer = getTimer(); - if( timer - 1000 > ms_prev ) - { + if( timer - 1000 > ms_prev ) { + ms_prev = timer; mem = Number((System.totalMemory * 0.000000954).toFixed(3)); mem_max = mem_max > mem ? mem_max : mem; - fps_graph = Math.min( graph.height, ( fps / stage.frameRate ) * graph.height ); - mem_graph = Math.min( graph.height, Math.sqrt( Math.sqrt( mem * 5000 ) ) ) - 2; - mem_max_graph = Math.min( graph.height, Math.sqrt( Math.sqrt( mem_max * 5000 ) ) ) - 2; + fps_graph = Math.min(graph.height, ( fps / stage.frameRate ) * graph.height); + mem_graph = Math.min(graph.height, Math.sqrt(Math.sqrt(mem * 5000))) - 2; + mem_max_graph = Math.min(graph.height, Math.sqrt(Math.sqrt(mem_max * 5000))) - 2; - graph.bitmapData.scroll( -1, 0 ); + graph.scroll(-1, 0); - graph.bitmapData.fillRect( rectangle , theme.bg ); - graph.bitmapData.setPixel( graph.width - 1, graph.height - fps_graph, theme.fps); - graph.bitmapData.setPixel( graph.width - 1, graph.height - ( ( timer - ms ) >> 1 ), theme.ms ); - graph.bitmapData.setPixel( graph.width - 1, graph.height - mem_graph, theme.mem); - graph.bitmapData.setPixel( graph.width - 1, graph.height - mem_max_graph, theme.memmax); + graph.fillRect(rectangle, colors.bg); + graph.setPixel(graph.width - 1, graph.height - fps_graph, colors.fps); + graph.setPixel(graph.width - 1, graph.height - ( ( timer - ms ) >> 1 ), colors.ms); + graph.setPixel(graph.width - 1, graph.height - mem_graph, colors.mem); + graph.setPixel(graph.width - 1, graph.height - mem_max_graph, colors.memmax); - xml.fps = "FPS: " + fps + " / " + stage.frameRate; + xml.fps = "FPS: " + fps + " / " + stage.frameRate; xml.mem = "MEM: " + mem; - xml.memMax = "MAX: " + mem_max; + xml.memMax = "MAX: " + mem_max; fps = 0; + } fps++; @@ -158,19 +149,33 @@ package net.hires.debug text.htmlText = xml; } - - private function onClick(e : MouseEvent) : void - { + + private function onClick(e : MouseEvent) : void { + mouseY / height > .5 ? stage.frameRate-- : stage.frameRate++; - xml.fps = "FPS: " + fps + " / " + stage.frameRate; + xml.fps = "FPS: " + fps + " / " + stage.frameRate; text.htmlText = xml; + } - + // .. Utils - - private function hex2css( color : int ) : String - { + + private function hex2css( color : int ) : String { + return "#" + color.toString(16); + } + } + } + +class Colors { + + public var bg : uint = 0x000033; + public var fps : uint = 0xffff00; + public var ms : uint = 0x00ff00; + public var mem : uint = 0x00ffff; + public var memmax : uint = 0xff0070; + +} \ No newline at end of file diff --git a/src/net/hires/debug/Stats.hx b/src/net/hires/debug/Stats.hx new file mode 100644 index 0000000..e026e84 --- /dev/null +++ b/src/net/hires/debug/Stats.hx @@ -0,0 +1,187 @@ +/** + * stats.hx + * http://github.com/mrdoob/stats.as + * + * Released under MIT license: + * http://www.opensource.org/licenses/mit-license.php + * + * How to use: + * + * addChild( new Stats() ); + * + **/ + +package net.hires.debug; + +import flash.display.BitmapData; +import flash.display.Sprite; +import flash.display.Stage; +import flash.events.Event; +import flash.events.MouseEvent; +import flash.geom.Matrix; +import flash.geom.Rectangle; +import flash.system.System; +import flash.text.StyleSheet; +import flash.text.TextField; +import flash.xml.XML; + + +class Stats extends Sprite { + + static inline var GRAPH_WIDTH : Int = 70; + static inline var XPOS : Int = 69;//width - 1 + static inline var GRAPH_HEIGHT : Int = 50; + static inline var TEXT_HEIGHT : Int = 50; + + private var xml : XML; + + private var text : TextField; + private var style : StyleSheet; + + private var timer : Int; + private var fps : Int; + private var ms : Int; + private var ms_prev : Int; + private var mem : Float; + private var mem_max : Float; + + private var graph : BitmapData; + private var rectangle : Rectangle; + + private var fps_graph : Int; + private var mem_graph : Int; + private var ms_graph : Int; + private var mem_max_graph : Int; + private var _stage:Stage; + + /** + * Stats FPS, MS and MEM, all in one. + */ + public function new() { + + super(); + mem_max = 0; + fps = 0; + + + xml = new XML("FPS:MS:MEM:MAX:"); + + style = new StyleSheet(); + style.setStyle('xml', {fontSize:'9px', fontFamily:'_sans', leading:'-2px'}); + style.setStyle('fps', {color: Colors.fpsCSS }); + style.setStyle('ms', {color: Colors.msCSS }); + style.setStyle('mem', {color: Colors.memCSS }); + style.setStyle('memMax', {color: Colors.memmaxCSS }); + + text = new TextField(); + text.width = GRAPH_WIDTH; + text.height = TEXT_HEIGHT; + text.styleSheet = style; + text.condenseWhite = true; + text.selectable = false; + text.mouseEnabled = false; + + rectangle = new Rectangle(GRAPH_WIDTH - 1, 0, 1, GRAPH_HEIGHT); + + this.addEventListener(Event.ADDED_TO_STAGE, init, false, 0, true); + this.addEventListener(Event.REMOVED_FROM_STAGE, destroy, false, 0, true); + + } + + private function init(e : Event) { + + _stage = flash.Lib.current.stage; + graphics.beginFill(Colors.bg); + graphics.drawRect(0, 0, GRAPH_WIDTH, TEXT_HEIGHT); + graphics.endFill(); + + this.addChild(text); + + graph = new BitmapData(GRAPH_WIDTH, GRAPH_HEIGHT, false, Colors.bg); + graphics.beginBitmapFill(graph, new Matrix(1, 0, 0, 1, 0, TEXT_HEIGHT)); + graphics.drawRect(0, TEXT_HEIGHT, GRAPH_WIDTH, GRAPH_HEIGHT); + + this.addEventListener(Event.ENTER_FRAME, update); + + } + + private function destroy(e : Event) { + + graphics.clear(); + + while(numChildren > 0) + removeChildAt(0); + + graph.dispose(); + + removeEventListener(Event.ENTER_FRAME, update); + + } + + private function update(e : Event) { + + timer = flash.Lib.getTimer(); + + //after a second has passed + if( timer - 1000 > ms_prev ) { + + mem = System.totalMemory * 0.000000954; + mem_max = mem_max > mem ? mem_max : mem; + + fps_graph = GRAPH_HEIGHT - Std.int( Math.min(GRAPH_HEIGHT, ( fps / _stage.frameRate ) * GRAPH_HEIGHT) ); + + mem_graph = GRAPH_HEIGHT - normalizeMem(mem); + mem_max_graph = GRAPH_HEIGHT - normalizeMem(mem_max); + //milliseconds since last frame -- this fluctuates quite a bit + ms_graph = Std.int( GRAPH_HEIGHT - ( ( timer - ms ) >> 1 )); + graph.scroll(-1, 0); + + graph.fillRect(rectangle, Colors.bg); + graph.lock(); + graph.setPixel(XPOS, fps_graph, Colors.fps); + graph.setPixel(XPOS, mem_graph, Colors.mem); + graph.setPixel(XPOS, mem_max_graph, Colors.memmax); + graph.setPixel(XPOS, ms_graph, Colors.ms); + graph.unlock(); + + xml.fps = "FPS: " + fps + " / " + stage.frameRate; + xml.mem = "MEM: " + mem; + xml.memMax = "MAX: " + mem_max; + + //reset frame and time counters + fps = 0; + ms_prev = timer; + + return; + } + //increment number of frames which have occurred in current second + fps++; + + xml.ms = "MS: " + (timer - ms); + ms = timer; + + text.htmlText = xml.toString(); + } + + + + function normalizeMem(_mem:Float):Int { + return Std.int( Math.min( GRAPH_HEIGHT, Math.sqrt(Math.sqrt(_mem * 5000)) ) - 2); + } + +} + +class Colors { + + public static inline var bg : Int = 0x000033; + public static inline var fps : Int = 0xffff00; + public static inline var ms : Int = 0x00ff00; + public static inline var mem : Int = 0x00ffff; + public static inline var memmax : Int = 0xff0070; + public static inline var bgCSS : String = "#000033"; + public static inline var fpsCSS : String = "#ffff00"; + public static inline var msCSS : String = "#00ff00"; + public static inline var memCSS : String = "#00ffff"; + public static inline var memmaxCSS : String = "#ff0070"; + +}