PageRenderTime 62ms CodeModel.GetById 32ms RepoModel.GetById 1ms app.codeStats 0ms

/src/com/elad/optimize/memory/FrameStats.hx

http://github.com/cambiata/cx
Haxe | 426 lines | 301 code | 86 blank | 39 comment | 22 complexity | a998806b5c542123f6a0152b8c8b6a1c MD5 | raw file
  1. /*
  2. Copyright (c) 2009 Elad Elrom. Elrom LLC. All rights reserved.
  3. Permission is hereby granted, free of charge, to any person
  4. obtaining a copy of this software and associated documentation
  5. files (the "Software"), to deal in the Software without
  6. restriction, including without limitation the rights to use,
  7. copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. copies of the Software, and to permit persons to whom the
  9. Software is furnished to do so, subject to the following
  10. conditions:
  11. The above copyright notice and this permission notice shall be
  12. included in all copies or substantial portions of the Software.
  13. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  14. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  15. OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  16. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  17. HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  18. WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20. OTHER DEALINGS IN THE SOFTWARE.
  21. @author Elad Elrom
  22. */
  23. package com.elad.optimize.memory;
  24. import flash.display.MovieClip;
  25. import flash.display.Shape;
  26. import flash.display.Sprite;
  27. import flash.events.Event;
  28. import flash.events.MouseEvent;
  29. import flash.events.TimerEvent;
  30. import flash.system.System;
  31. import flash.text.TextField;
  32. import flash.text.TextFormat;
  33. import flash.utils.Timer;
  34. import flash.Lib;
  35. //using primevc.utils.FloatUtil;
  36. using StringTools;
  37. class FrameStats extends Sprite
  38. {
  39. private static inline var LINE_GRAPH_STARTING_POINT_X:Int = 85;
  40. public static inline var WIDTH:Int = 200;
  41. public static inline var HEIGHT:Int = 100;
  42. private var isShowCounters:Bool;
  43. private var isForceInvalidateAndUpdateAfterEvent:Bool;
  44. private var countSecondsSinceStart:Int;
  45. private var main:Sprite;
  46. // Enter frame
  47. private var frameActionsExecuted:Float;
  48. private var enterFrameCounter:Int;
  49. private var enterFrameTime:Float;
  50. // Enter frame constructed
  51. private var constructorCodeExecuted:Float;
  52. private var enterFrameConstructedCounter:Int;
  53. private var enterFrameConstructedTime:Float;
  54. // exit frame
  55. private var exitFrameCounter:Int;
  56. private var exitFrameTime:Float;
  57. // rendering
  58. private var playerRendersChangesDisplayList:Float;
  59. private var renderingCounter:Int;
  60. private var renderingTime:Float;
  61. // final code exec
  62. private var finalUserCodeExecuted:Float;
  63. private var isFinalUserCodeFirstTime:Bool;
  64. private var finalUserCodeTime:Float;
  65. private var firstFinalUserCodeTime:Float;
  66. // timer
  67. private var startTime:Float;
  68. private var timer:Timer;
  69. private var mouseEventCounter:Int;
  70. // charts colors
  71. private var colors:flash.Vector<Int>;
  72. // texts
  73. private var format:TextFormat;
  74. private var pieText:TextField;
  75. private var globalText:TextField;
  76. // graphs
  77. private var lineGraphCounter:Int;
  78. private var lineGraphs:flash.Vector<Sprite>;
  79. private var pieGraph:MovieClip;
  80. private var drawBackground (getDrawBackground, null) : Sprite;
  81. // charts data provider
  82. private var dataProvider:flash.Vector<TimerVO>;
  83. public function new( main:Sprite, isShowCounters:Bool = false,
  84. isForceInvalidateAndUpdateAfterEvent:Bool = false )
  85. {
  86. super();
  87. startTime = Lib.getTimer();
  88. timer = new Timer(1000);
  89. countSecondsSinceStart = 0;
  90. isFinalUserCodeFirstTime = false;
  91. colors = new flash.Vector();
  92. lineGraphs = new flash.Vector<Sprite>();
  93. lineGraphCounter = 0;
  94. pieText = new TextField();
  95. globalText = new TextField();
  96. this.main = main;
  97. this.isShowCounters = isShowCounters;
  98. this.isForceInvalidateAndUpdateAfterEvent = isForceInvalidateAndUpdateAfterEvent;
  99. colors.push(0xe48701);
  100. colors.push(0xa5bc4e);
  101. colors.push(0x1b95d9);
  102. colors.push(0xcaca9e);
  103. addEventListener(Event.ENTER_FRAME, updateDisplay);
  104. setStyles();
  105. addChild( drawBackground );
  106. addChild( pieText );
  107. addChild( globalText );
  108. drawLineGraph();
  109. drawRects();
  110. timer.addEventListener( TimerEvent.TIMER, showResults );
  111. timer.start();
  112. synthesizesFrameRate();
  113. }
  114. private inline function getDrawBackground():Sprite
  115. {
  116. var sprite:Sprite = new Sprite();
  117. sprite.graphics.beginFill(0x000025);
  118. sprite.graphics.drawRect(0, 0, WIDTH, HEIGHT);
  119. sprite.graphics.endFill();
  120. return sprite;
  121. }
  122. private inline function drawRects():Void
  123. {
  124. var rectangle:Shape;
  125. var startY:Float = 66.5;
  126. for (color in colors) {
  127. startY += 6.1;
  128. rectangle = new Shape();
  129. rectangle.graphics.beginFill(color);
  130. rectangle.graphics.drawRect(0, 0, 5, 5);
  131. rectangle.graphics.endFill();
  132. rectangle.x = 0;
  133. rectangle.y = startY;
  134. addChild(rectangle);
  135. }
  136. }
  137. private inline function drawLineGraph():Void
  138. {
  139. var item:Sprite;
  140. for (i in 0...4)
  141. {
  142. item = new Sprite();
  143. item.graphics.lineStyle( 1, colors[i] );
  144. item.graphics.moveTo( LINE_GRAPH_STARTING_POINT_X, 0 );
  145. lineGraphs.push( item );
  146. addChild( item );
  147. }
  148. }
  149. private inline function setTextProp( text:TextField, x:Int, y:Int, width:Int, height:Int ):Void
  150. {
  151. text.mouseEnabled = false;
  152. text.condenseWhite = true;
  153. text.selectable = false;
  154. text.multiline = true;
  155. text.x = x;
  156. text.y = y;
  157. text.width = width;
  158. text.height = height;
  159. text.setTextFormat( format );
  160. text.defaultTextFormat = format;
  161. }
  162. private inline function updateDisplay( event:Event ):Void
  163. {
  164. if (dataProvider == null)
  165. return;
  166. var total:Float = 0;
  167. ++lineGraphCounter;
  168. for (timerVO in dataProvider)
  169. total += timerVO.time;
  170. drawGraph( 25, dataProvider, total );
  171. updateLabels( dataProvider );
  172. }
  173. private inline function synthesizesFrameRate():Void
  174. {
  175. main.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler );
  176. main.addEventListener(Event.ENTER_FRAME, enterFrameHandler );
  177. main.addEventListener(Event.FRAME_CONSTRUCTED, frameConstructedHandler );
  178. main.addEventListener(Event.EXIT_FRAME, exitFrameHandler);
  179. main.addEventListener(Event.RENDER, renderHandler);
  180. }
  181. private inline function showResults(?event):Void
  182. {
  183. ++countSecondsSinceStart;
  184. #if (debug && debugFrameStats)
  185. trace("-------------- " + countSecondsSinceStart + " second ---------------");
  186. if (isShowCounters)
  187. {
  188. trace("------ counters -----");
  189. trace("enterFrameCounter: " + enterFrameCounter );
  190. trace("renderingCounter: " + renderingCounter );
  191. trace("mouseEventCounter: " + mouseEventCounter );
  192. }
  193. #end
  194. enterFrameCounter = 0;
  195. mouseEventCounter = 0;
  196. renderingCounter = 0;
  197. }
  198. private inline function setNewDataProvider():Void
  199. {
  200. var total = constructorCodeExecuted + frameActionsExecuted + finalUserCodeExecuted + playerRendersChangesDisplayList;
  201. dataProvider = new flash.Vector<TimerVO>();
  202. dataProvider.push( new TimerVO("Constructor code executed", (constructorCodeExecuted / total * 100 ).round(2) ));
  203. dataProvider.push( new TimerVO("frame actions executed", (frameActionsExecuted / total * 100 ).round(2) ));
  204. dataProvider.push( new TimerVO("Final user code executed", (finalUserCodeExecuted / total * 100 ).round(2) ));
  205. dataProvider.push( new TimerVO("Player renders changes display list", (playerRendersChangesDisplayList / total * 100 ).round(2) ));
  206. }
  207. private inline function drawGraph( radius:Int, dataProvider:flash.Vector<TimerVO>, total:Float ):Void
  208. {
  209. if (pieGraph != null)
  210. removeChild( pieGraph );
  211. addChild( pieGraph = new MovieClip() );
  212. var numOfRadians:Float = 0;
  213. pieGraph.x = 30;
  214. pieGraph.y = 46;
  215. pieGraph.graphics.lineStyle( 1, 0x000000 );
  216. var radian:Float;
  217. var title:String;
  218. var index:Int = 0;
  219. for (timerVO in dataProvider)
  220. {
  221. // draw line graph
  222. if ( lineGraphCounter > WIDTH - LINE_GRAPH_STARTING_POINT_X )
  223. resetLineGraph();
  224. lineGraphs[index].graphics.lineTo( LINE_GRAPH_STARTING_POINT_X + lineGraphCounter , ( 100-dataProvider[index].time ) );
  225. // draw pie
  226. radian = timerVO.time / total * 2;
  227. title = timerVO.name;
  228. pieGraph.graphics.beginFill( colors[index] );
  229. pieGraph.graphics.moveTo( 0,0 );
  230. pieGraph.graphics.lineTo( Math.sin( numOfRadians * Math.PI ) * radius, Math.cos( numOfRadians * Math.PI ) * radius );
  231. var n:Float = 0;
  232. while (n <= radian) {
  233. pieGraph.graphics.lineTo( Math.sin( ( numOfRadians+n ) * Math.PI ) * radius, Math.cos( ( numOfRadians+n ) * Math.PI ) * radius );
  234. n += 0.0001;
  235. }
  236. numOfRadians += radian;
  237. pieGraph.graphics.lineTo( 0,0 );
  238. pieGraph.graphics.endFill();
  239. index++;
  240. }
  241. }
  242. private inline function resetLineGraph():Void
  243. {
  244. lineGraphCounter = 0;
  245. var index = 0;
  246. for (item in lineGraphs) {
  247. item.graphics.clear();
  248. item.graphics.lineStyle(1, colors[index]);
  249. item.graphics.moveTo(LINE_GRAPH_STARTING_POINT_X, 0);
  250. index++;
  251. }
  252. }
  253. private inline function setStyles():Void
  254. {
  255. format = new TextFormat("_sans", 7);
  256. format.leading = -2;
  257. setTextProp( globalText, 4, -2, 70, 30 );
  258. setTextProp( pieText, 4, 70, LINE_GRAPH_STARTING_POINT_X, 30 );
  259. }
  260. private inline function updateLabels(dataProvider:flash.Vector<TimerVO>):Void
  261. {
  262. var pieTexts = [];
  263. pieTexts.push( '<font color="#'+colors[0].hex()+'">Constructor 2: '+ dataProvider[0].time + '</font>' );
  264. pieTexts.push( '<font color="#'+colors[1].hex()+'">Frame Actions: '+ dataProvider[1].time + '</font>' );
  265. pieTexts.push( '<font color="#'+colors[2].hex()+'">Final UserCode: '+ dataProvider[2].time + '</font>' );
  266. pieTexts.push( '<font color="#'+colors[3].hex()+'">Display changes: '+ dataProvider[3].time + '</font>' );
  267. var globalTexts = [];
  268. globalTexts.push( '<font color="#ffffff">FPS: '+ stage.frameRate + '</font>' );
  269. globalTexts.push( '<font color="#ffffff">MEM: '+ ( System.totalMemory * 0.000000954 ).round(2) + '</font>' );
  270. globalTexts.push( '<font color="#ffffff">TIME: '+ countSecondsSinceStart + '</font>' );
  271. globalText.htmlText = globalTexts.join("\n<br>");
  272. pieText.htmlText = pieTexts.join("\n<br>");
  273. }
  274. private function mouseMoveHandler (event) {
  275. mouseEventCounter++;
  276. finalUserCodeTime = Lib.getTimer() - startTime;
  277. if ( renderingTime != 0 && isFinalUserCodeFirstTime )
  278. {
  279. isFinalUserCodeFirstTime = false;
  280. firstFinalUserCodeTime = Lib.getTimer()-startTime;
  281. }
  282. #if (debug && debugFrameStats)
  283. trace("MouseEvent.MOUSE_MOVE");
  284. #end
  285. if (isForceInvalidateAndUpdateAfterEvent)
  286. {
  287. stage.invalidate();
  288. event.updateAfterEvent();
  289. }
  290. }
  291. private function enterFrameHandler (event) {
  292. isFinalUserCodeFirstTime = true;
  293. enterFrameCounter++;
  294. enterFrameTime = Lib.getTimer() - startTime;
  295. finalUserCodeExecuted = finalUserCodeTime-firstFinalUserCodeTime;
  296. playerRendersChangesDisplayList = enterFrameTime-finalUserCodeTime;
  297. #if (debug && debugFrameStats)
  298. trace("Final user code executed: " + String( finalUserCodeExecuted ) );
  299. trace("Player renders changes display list: " + String( playerRendersChangesDisplayList ) );
  300. trace("Event.ENTER_FRAME");
  301. #end
  302. setNewDataProvider();
  303. }
  304. private function frameConstructedHandler (event) {
  305. enterFrameConstructedCounter++;
  306. enterFrameConstructedTime = Lib.getTimer() - startTime;
  307. constructorCodeExecuted = enterFrameConstructedTime-enterFrameTime;
  308. #if (debug && debugFrameStats)
  309. trace("Constructor code of children executed: " + String( constructorCodeExecuted ) );
  310. #end
  311. }
  312. private function exitFrameHandler (event) {
  313. exitFrameCounter++;
  314. exitFrameTime = Lib.getTimer() - startTime;
  315. frameActionsExecuted = exitFrameTime-enterFrameConstructedTime;
  316. #if (debug && debugFrameStats)
  317. trace("frame actions & children executed: " + String( frameActionsExecuted ) );
  318. #end
  319. }
  320. private function renderHandler (event) {
  321. renderingCounter++;
  322. renderingTime = Lib.getTimer() - startTime;
  323. #if (debug && debugFrameStats)
  324. trace("Event.RENDER");
  325. #end
  326. }
  327. }
  328. class TimerVO
  329. {
  330. public var name : String;
  331. public var time : Float;
  332. public function new (name, time) {
  333. this.name = name;
  334. this.time = time;
  335. }
  336. }