Accumulator.html 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  5. <title>The source code</title>
  6. <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
  7. <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
  8. <style type="text/css">
  9. .highlight { display: block; background-color: #ddd; }
  10. </style>
  11. <script type="text/javascript">
  12. function highlight() {
  13. document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
  14. }
  15. </script>
  16. </head>
  17. <body onload="prettyPrint(); highlight();">
  18. <pre class="prettyprint lang-js"><span id='Ext-perf-Accumulator'>/**
  19. </span> * @class Ext.perf.Accumulator
  20. * @private
  21. */
  22. Ext.define('Ext.perf.Accumulator', (function () {
  23. var currentFrame = null,
  24. khrome = Ext.global['chrome'],
  25. formatTpl,
  26. // lazy init on first request for timestamp (avoids infobar in IE until needed)
  27. // Also avoids kicking off Chrome's microsecond timer until first needed
  28. getTimestamp = function () {
  29. getTimestamp = function () {
  30. return new Date().getTime();
  31. };
  32. var interval, toolbox;
  33. // If Chrome is started with the --enable-benchmarking switch
  34. if (Ext.isChrome &amp;&amp; khrome &amp;&amp; khrome.Interval) {
  35. interval = new khrome.Interval();
  36. interval.start();
  37. getTimestamp = function () {
  38. return interval.microseconds() / 1000;
  39. };
  40. } else if (window.ActiveXObject) {
  41. try {
  42. // the above technique is not very accurate for small intervals...
  43. toolbox = new ActiveXObject('SenchaToolbox.Toolbox');
  44. Ext.senchaToolbox = toolbox; // export for other uses
  45. getTimestamp = function () {
  46. return toolbox.milliseconds;
  47. };
  48. } catch (e) {
  49. // ignore
  50. }
  51. } else if (Date.now) {
  52. getTimestamp = Date.now;
  53. }
  54. Ext.perf.getTimestamp = Ext.perf.Accumulator.getTimestamp = getTimestamp;
  55. return getTimestamp();
  56. };
  57. function adjustSet (set, time) {
  58. set.sum += time;
  59. set.min = Math.min(set.min, time);
  60. set.max = Math.max(set.max, time);
  61. }
  62. function leaveFrame (time) {
  63. var totalTime = time ? time : (getTimestamp() - this.time), // do this first
  64. me = this, // me = frame
  65. accum = me.accum;
  66. ++accum.count;
  67. if (! --accum.depth) {
  68. adjustSet(accum.total, totalTime);
  69. }
  70. adjustSet(accum.pure, totalTime - me.childTime);
  71. currentFrame = me.parent;
  72. if (currentFrame) {
  73. ++currentFrame.accum.childCount;
  74. currentFrame.childTime += totalTime;
  75. }
  76. }
  77. function makeSet () {
  78. return {
  79. min: Number.MAX_VALUE,
  80. max: 0,
  81. sum: 0
  82. };
  83. }
  84. function makeTap (me, fn) {
  85. return function () {
  86. var frame = me.enter(),
  87. ret = fn.apply(this, arguments);
  88. frame.leave();
  89. return ret;
  90. };
  91. }
  92. function round (x) {
  93. return Math.round(x * 100) / 100;
  94. }
  95. function setToJSON (count, childCount, calibration, set) {
  96. var data = {
  97. avg: 0,
  98. min: set.min,
  99. max: set.max,
  100. sum: 0
  101. };
  102. if (count) {
  103. calibration = calibration || 0;
  104. data.sum = set.sum - childCount * calibration;
  105. data.avg = data.sum / count;
  106. // min and max cannot be easily corrected since we don't know the number of
  107. // child calls for them.
  108. }
  109. return data;
  110. }
  111. return {
  112. constructor: function (name) {
  113. var me = this;
  114. me.count = me.childCount = me.depth = me.maxDepth = 0;
  115. me.pure = makeSet();
  116. me.total = makeSet();
  117. me.name = name;
  118. },
  119. statics: {
  120. getTimestamp: getTimestamp
  121. },
  122. format: function (calibration) {
  123. if (!formatTpl) {
  124. formatTpl = new Ext.XTemplate([
  125. '{name} - {count} call(s)',
  126. '&lt;tpl if=&quot;count&quot;&gt;',
  127. '&lt;tpl if=&quot;childCount&quot;&gt;',
  128. ' ({childCount} children)',
  129. '&lt;/tpl&gt;',
  130. '&lt;tpl if=&quot;depth - 1&quot;&gt;',
  131. ' ({depth} deep)',
  132. '&lt;/tpl&gt;',
  133. '&lt;tpl for=&quot;times&quot;&gt;',
  134. ', {type}: {[this.time(values.sum)]} msec (',
  135. //'min={[this.time(values.min)]}, ',
  136. 'avg={[this.time(values.sum / parent.count)]}',
  137. //', max={[this.time(values.max)]}',
  138. ')',
  139. '&lt;/tpl&gt;',
  140. '&lt;/tpl&gt;'
  141. ].join(''), {
  142. time: function (t) {
  143. return Math.round(t * 100) / 100;
  144. }
  145. });
  146. }
  147. var data = this.getData(calibration);
  148. data.name = this.name;
  149. data.pure.type = 'Pure';
  150. data.total.type = 'Total';
  151. data.times = [data.pure, data.total];
  152. return formatTpl.apply(data);
  153. },
  154. getData: function (calibration) {
  155. var me = this;
  156. return {
  157. count: me.count,
  158. childCount: me.childCount,
  159. depth: me.maxDepth,
  160. pure: setToJSON(me.count, me.childCount, calibration, me.pure),
  161. total: setToJSON(me.count, me.childCount, calibration, me.total)
  162. };
  163. },
  164. enter: function () {
  165. var me = this,
  166. frame = {
  167. accum: me,
  168. leave: leaveFrame,
  169. childTime: 0,
  170. parent: currentFrame
  171. };
  172. ++me.depth;
  173. if (me.maxDepth &lt; me.depth) {
  174. me.maxDepth = me.depth;
  175. }
  176. currentFrame = frame;
  177. frame.time = getTimestamp(); // do this last
  178. return frame;
  179. },
  180. monitor: function (fn, scope, args) {
  181. var frame = this.enter();
  182. if (args) {
  183. fn.apply(scope, args);
  184. } else {
  185. fn.call(scope);
  186. }
  187. frame.leave();
  188. },
  189. report: function () {
  190. Ext.log(this.format());
  191. },
  192. tap: function (className, methodName) {
  193. var me = this,
  194. methods = typeof methodName == 'string' ? [methodName] : methodName,
  195. klass, statik, i, parts, length, name, src,
  196. tapFunc;
  197. tapFunc = function(){
  198. if (typeof className == 'string') {
  199. klass = Ext.global;
  200. parts = className.split('.');
  201. for (i = 0, length = parts.length; i &lt; length; ++i) {
  202. klass = klass[parts[i]];
  203. }
  204. } else {
  205. klass = className;
  206. }
  207. for (i = 0, length = methods.length; i &lt; length; ++i) {
  208. name = methods[i];
  209. statik = name.charAt(0) == '!';
  210. if (statik) {
  211. name = name.substring(1);
  212. } else {
  213. statik = !(name in klass.prototype);
  214. }
  215. src = statik ? klass : klass.prototype;
  216. src[name] = makeTap(me, src[name]);
  217. }
  218. };
  219. Ext.ClassManager.onCreated(tapFunc, me, className);
  220. return me;
  221. }
  222. };
  223. }()),
  224. function () {
  225. Ext.perf.getTimestamp = this.getTimestamp;
  226. });
  227. </pre>
  228. </body>
  229. </html>