[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 YUI.add('yui2-profiler', function(Y) { 2 var YAHOO = Y.YUI2; 3 /* 4 Copyright (c) 2011, Yahoo! Inc. All rights reserved. 5 Code licensed under the BSD License: 6 http://developer.yahoo.com/yui/license.html 7 version: 2.9.0 8 */ 9 YAHOO.namespace("tool"); 10 11 /** 12 * The YUI JavaScript profiler. 13 * @module profiler 14 * @namespace YAHOO.tool 15 * @requires yahoo 16 */ 17 18 /** 19 * Profiles functions in JavaScript. 20 * @namespace YAHOO.tool 21 * @class Profiler 22 * @static 23 */ 24 YAHOO.tool.Profiler = function(){ 25 26 27 //------------------------------------------------------------------------- 28 // Private Variables and Functions 29 //------------------------------------------------------------------------- 30 31 var container = {}, //Container object on which to put the original unprofiled methods. 32 report = {}, //Profiling information for functions 33 stopwatches = {}, //Additional stopwatch information 34 35 WATCH_STARTED = 0, 36 WATCH_STOPPED = 1, 37 WATCH_PAUSED = 2, 38 39 lang = YAHOO.lang; 40 41 /** 42 * Creates a report object with the given name. 43 * @param {String} name The name to store for the report object. 44 * @return {Void} 45 * @method createReport 46 * @private 47 */ 48 function createReport(name){ 49 report[name] = { 50 calls: 0, 51 max: 0, 52 min: 0, 53 avg: 0, 54 points: [] 55 }; 56 } 57 58 /** 59 * Called when a method ends execution. Marks the start and end time of the 60 * method so it can calculate how long the function took to execute. Also 61 * updates min/max/avg calculations for the function. 62 * @param {String} name The name of the function to mark as stopped. 63 * @param {int} duration The number of milliseconds it took the function to 64 * execute. 65 * @return {Void} 66 * @method saveDataPoint 67 * @private 68 * @static 69 */ 70 function saveDataPoint(name, duration){ 71 72 //get the function data 73 var functionData /*:Object*/ = report[name]; 74 75 //just in case clear() was called 76 if (!functionData){ 77 functionData = createReport(name); 78 } 79 80 //increment the calls 81 functionData.calls++; 82 functionData.points.push(duration); 83 84 //if it's already been called at least once, do more complex calculations 85 if (functionData.calls > 1) { 86 functionData.avg = ((functionData.avg*(functionData.calls-1))+duration)/functionData.calls; 87 functionData.min = Math.min(functionData.min, duration); 88 functionData.max = Math.max(functionData.max, duration); 89 } else { 90 functionData.avg = duration; 91 functionData.min = duration; 92 functionData.max = duration; 93 } 94 95 } 96 97 //------------------------------------------------------------------------- 98 // Singleton Object 99 //------------------------------------------------------------------------- 100 101 return { 102 103 //------------------------------------------------------------------------- 104 // Utility Methods 105 //------------------------------------------------------------------------- 106 107 /** 108 * Removes all report data from the profiler. 109 * @param {String} name (Optional) The name of the report to clear. If 110 * omitted, then all report data is cleared. 111 * @return {Void} 112 * @method clear 113 * @static 114 */ 115 clear: function(name){ 116 if (lang.isString(name)){ 117 delete report[name]; 118 delete stopwatches[name]; 119 } else { 120 report = {}; 121 stopwatches = {}; 122 } 123 }, 124 125 /** 126 * Returns the uninstrumented version of a function/object. 127 * @param {String} name The name of the function/object to retrieve. 128 * @return {Function|Object} The uninstrumented version of a function/object. 129 * @method getOriginal 130 * @static 131 */ 132 getOriginal: function(name){ 133 return container[name]; 134 }, 135 136 /** 137 * Instruments a method to have profiling calls. 138 * @param {String} name The name of the report for the function. 139 * @param {Function} method The function to instrument. 140 * @return {Function} An instrumented version of the function. 141 * @method instrument 142 * @static 143 */ 144 instrument: function(name, method){ 145 146 //create instrumented version of function 147 var newMethod = function () { 148 149 var start = new Date(), 150 retval = method.apply(this, arguments), 151 stop = new Date(); 152 153 saveDataPoint(name, stop-start); 154 155 return retval; 156 157 }; 158 159 //copy the function properties over 160 lang.augmentObject(newMethod, method); 161 162 //assign prototype and flag as being profiled 163 newMethod.__yuiProfiled = true; 164 newMethod.prototype = method.prototype; 165 166 //store original method 167 container[name] = method; 168 container[name].__yuiFuncName = name; 169 170 //create the report 171 createReport(name); 172 173 //return the new method 174 return newMethod; 175 }, 176 177 //------------------------------------------------------------------------- 178 // Stopwatch Methods 179 //------------------------------------------------------------------------- 180 181 /** 182 * Pauses profiling information for a given name. 183 * @param {String} name The name of the data point. 184 * @return {Void} 185 * @method pause 186 * @static 187 */ 188 pause: function(name){ 189 var now = new Date(), 190 stopwatch = stopwatches[name]; 191 192 if (stopwatch && stopwatch.state == WATCH_STARTED){ 193 stopwatch.total += (now - stopwatch.start); 194 stopwatch.start = 0; 195 stopwatch.state = WATCH_PAUSED; 196 } 197 198 }, 199 200 /** 201 * Start profiling information for a given name. The name cannot be the name 202 * of a registered function or object. This is used to start timing for a 203 * particular block of code rather than instrumenting the entire function. 204 * @param {String} name The name of the data point. 205 * @return {Void} 206 * @method start 207 * @static 208 */ 209 start: function(name){ 210 if(container[name]){ 211 throw new Error("Cannot use '" + name + "' for profiling through start(), name is already in use."); 212 } else { 213 214 //create report if necessary 215 if (!report[name]){ 216 createReport(name); 217 } 218 219 //create stopwatch object if necessary 220 if (!stopwatches[name]){ 221 stopwatches[name] = { 222 state: WATCH_STOPPED, 223 start: 0, 224 total: 0 225 }; 226 } 227 228 if (stopwatches[name].state == WATCH_STOPPED){ 229 stopwatches[name].state = WATCH_STARTED; 230 stopwatches[name].start = new Date(); 231 } 232 233 } 234 }, 235 236 /** 237 * Stops profiling information for a given name. 238 * @param {String} name The name of the data point. 239 * @return {Void} 240 * @method stop 241 * @static 242 */ 243 stop: function(name){ 244 var now = new Date(), 245 stopwatch = stopwatches[name]; 246 247 if (stopwatch){ 248 if (stopwatch.state == WATCH_STARTED){ 249 saveDataPoint(name, stopwatch.total + (now - stopwatch.start)); 250 } else if (stopwatch.state == WATCH_PAUSED){ 251 saveDataPoint(name, stopwatch.total); 252 } 253 254 //reset stopwatch information 255 stopwatch.start = 0; 256 stopwatch.total = 0; 257 stopwatch.state = WATCH_STOPPED; 258 } 259 }, 260 261 //------------------------------------------------------------------------- 262 // Reporting Methods 263 //------------------------------------------------------------------------- 264 265 /** 266 * Returns the average amount of time (in milliseconds) that the function 267 * with the given name takes to execute. 268 * @param {String} name The name of the function whose data should be returned. 269 * If an object type method, it should be 'constructor.prototype.methodName'; 270 * a normal object method would just be 'object.methodName'. 271 * @return {float} The average time it takes the function to execute. 272 * @method getAverage 273 * @static 274 */ 275 getAverage : function (name /*:String*/) /*:float*/ { 276 return report[name].avg; 277 }, 278 279 /** 280 * Returns the number of times that the given function has been called. 281 * @param {String} name The name of the function whose data should be returned. 282 * @return {int} The number of times the function was called. 283 * @method getCallCount 284 * @static 285 */ 286 getCallCount : function (name /*:String*/) /*:int*/ { 287 return report[name].calls; 288 }, 289 290 /** 291 * Returns the maximum amount of time (in milliseconds) that the function 292 * with the given name takes to execute. 293 * @param {String} name The name of the function whose data should be returned. 294 * If an object type method, it should be 'constructor.prototype.methodName'; 295 * a normal object method would just be 'object.methodName'. 296 * @return {float} The maximum time it takes the function to execute. 297 * @method getMax 298 * @static 299 */ 300 getMax : function (name /*:String*/) /*:int*/ { 301 return report[name].max; 302 }, 303 304 /** 305 * Returns the minimum amount of time (in milliseconds) that the function 306 * with the given name takes to execute. 307 * @param {String} name The name of the function whose data should be returned. 308 * If an object type method, it should be 'constructor.prototype.methodName'; 309 * a normal object method would just be 'object.methodName'. 310 * @return {float} The minimum time it takes the function to execute. 311 * @method getMin 312 * @static 313 */ 314 getMin : function (name /*:String*/) /*:int*/ { 315 return report[name].min; 316 }, 317 318 /** 319 * Returns an object containing profiling data for a single function. 320 * The object has an entry for min, max, avg, calls, and points). 321 * @return {Object} An object containing profile data for a given function. 322 * @method getFunctionReport 323 * @static 324 * @deprecated Use getReport() instead. 325 */ 326 getFunctionReport : function (name /*:String*/) /*:Object*/ { 327 return report[name]; 328 }, 329 330 /** 331 * Returns an object containing profiling data for a single function. 332 * The object has an entry for min, max, avg, calls, and points). 333 * @return {Object} An object containing profile data for a given function. 334 * @method getReport 335 * @static 336 */ 337 getReport : function (name /*:String*/) /*:Object*/ { 338 return report[name]; 339 }, 340 341 /** 342 * Returns an object containing profiling data for all of the functions 343 * that were profiled. The object has an entry for each function and 344 * returns all information (min, max, average, calls, etc.) for each 345 * function. 346 * @return {Object} An object containing all profile data. 347 * @static 348 */ 349 getFullReport : function (filter /*:Function*/) /*:Object*/ { 350 filter = filter || function(){return true;}; 351 352 if (lang.isFunction(filter)) { 353 var fullReport = {}; 354 355 for (var name in report){ 356 if (filter(report[name])){ 357 fullReport[name] = report[name]; 358 } 359 } 360 361 return fullReport; 362 } 363 }, 364 365 //------------------------------------------------------------------------- 366 // Profiling Methods 367 //------------------------------------------------------------------------- 368 369 /** 370 * Sets up a constructor for profiling, including all properties and methods on the prototype. 371 * @param {string} name The fully-qualified name of the function including namespace information. 372 * @param {Object} owner (Optional) The object that owns the function (namespace or containing object). 373 * @return {Void} 374 * @method registerConstructor 375 * @static 376 */ 377 registerConstructor : function (name /*:String*/, owner /*:Object*/) /*:Void*/ { 378 this.registerFunction(name, owner, true); 379 }, 380 381 /** 382 * Sets up a function for profiling. It essentially overwrites the function with one 383 * that has instrumentation data. This method also creates an entry for the function 384 * in the profile report. The original function is stored on the container object. 385 * @param {String} name The full name of the function including namespacing. This 386 * is the name of the function that is stored in the report. 387 * @param {Object} owner (Optional) The object that owns the function. If the function 388 * isn't global then this argument is required. This could be the namespace that 389 * the function belongs to, such as YAHOO.util.Dom, or the object on which it's 390 * a method. 391 * @param {Boolean} registerPrototype (Optional) Indicates that the prototype should 392 * also be instrumented. Setting to true has the same effect as calling 393 * registerConstructor(). 394 * @return {Void} 395 * @method registerFunction 396 * @static 397 */ 398 registerFunction : function(name /*:String*/, owner /*:Object*/, registerPrototype /*:Boolean*/) /*:Void*/{ 399 400 //figure out the function name without namespacing 401 var funcName = (name.indexOf(".") > -1 ? 402 name.substring(name.lastIndexOf(".")+1) : name), 403 method, 404 prototype; 405 406 //if owner isn't an object, try to find it from the name 407 if (!lang.isObject(owner)){ 408 owner = eval(name.substring(0, name.lastIndexOf("."))); 409 } 410 411 //get the method and prototype 412 method = owner[funcName]; 413 prototype = method.prototype; 414 415 //see if the method has already been registered 416 if (lang.isFunction(method) && !method.__yuiProfiled){ 417 418 //replace the function with the profiling one 419 owner[funcName] = this.instrument(name, method); 420 421 /* 422 * Store original function information. We store the actual 423 * function as well as the owner and the name used to identify 424 * the function so it can be restored later. 425 */ 426 container[name].__yuiOwner = owner; 427 container[name].__yuiFuncName = funcName; //overwrite with less-specific name 428 429 //register prototype if necessary 430 if (registerPrototype) { 431 this.registerObject(name + ".prototype", prototype); 432 } 433 434 } 435 436 }, 437 438 439 /** 440 * Sets up an object for profiling. It takes the object and looks for functions. 441 * When a function is found, registerMethod() is called on it. If set to recrusive 442 * mode, it will also setup objects found inside of this object for profiling, 443 * using the same methodology. 444 * @param {String} name The name of the object to profile (shows up in report). 445 * @param {Object} owner (Optional) The object represented by the name. 446 * @param {Boolean} recurse (Optional) Determines if subobject methods are also profiled. 447 * @return {Void} 448 * @method registerObject 449 * @static 450 */ 451 registerObject : function (name /*:String*/, object /*:Object*/, recurse /*:Boolean*/) /*:Void*/{ 452 453 //get the object 454 object = (lang.isObject(object) ? object : eval(name)); 455 456 //save the object 457 container[name] = object; 458 459 for (var prop in object) { 460 if (typeof object[prop] == "function"){ 461 if (prop != "constructor" && prop != "superclass"){ //don't do constructor or superclass, it's recursive 462 this.registerFunction(name + "." + prop, object); 463 } 464 } else if (typeof object[prop] == "object" && recurse){ 465 this.registerObject(name + "." + prop, object[prop], recurse); 466 } 467 } 468 469 }, 470 471 /** 472 * Removes a constructor function from profiling. Reverses the registerConstructor() method. 473 * @param {String} name The full name of the function including namespacing. This 474 * is the name of the function that is stored in the report. 475 * @return {Void} 476 * @method unregisterFunction 477 * @static 478 */ 479 unregisterConstructor : function(name /*:String*/) /*:Void*/{ 480 481 //see if the method has been registered 482 if (lang.isFunction(container[name])){ 483 this.unregisterFunction(name, true); 484 } 485 }, 486 487 /** 488 * Removes function from profiling. Reverses the registerFunction() method. 489 * @param {String} name The full name of the function including namespacing. This 490 * is the name of the function that is stored in the report. 491 * @return {Void} 492 * @method unregisterFunction 493 * @static 494 */ 495 unregisterFunction : function(name /*:String*/, unregisterPrototype /*:Boolean*/) /*:Void*/{ 496 497 //see if the method has been registered 498 if (lang.isFunction(container[name])){ 499 500 //check to see if you should unregister the prototype 501 if (unregisterPrototype){ 502 this.unregisterObject(name + ".prototype", container[name].prototype); 503 } 504 505 //get original data 506 var owner /*:Object*/ = container[name].__yuiOwner, 507 funcName /*:String*/ = container[name].__yuiFuncName; 508 509 //delete extra information 510 delete container[name].__yuiOwner; 511 delete container[name].__yuiFuncName; 512 513 //replace instrumented function 514 owner[funcName] = container[name]; 515 516 //delete supporting information 517 delete container[name]; 518 } 519 520 521 }, 522 523 /** 524 * Unregisters an object for profiling. It takes the object and looks for functions. 525 * When a function is found, unregisterMethod() is called on it. If set to recrusive 526 * mode, it will also unregister objects found inside of this object, 527 * using the same methodology. 528 * @param {String} name The name of the object to unregister. 529 * @param {Boolean} recurse (Optional) Determines if subobject methods should also be 530 * unregistered. 531 * @return {Void} 532 * @method unregisterObject 533 * @static 534 */ 535 unregisterObject : function (name /*:String*/, recurse /*:Boolean*/) /*:Void*/{ 536 537 //get the object 538 if (lang.isObject(container[name])){ 539 var object = container[name]; 540 541 for (var prop in object) { 542 if (typeof object[prop] == "function"){ 543 this.unregisterFunction(name + "." + prop); 544 } else if (typeof object[prop] == "object" && recurse){ 545 this.unregisterObject(name + "." + prop, recurse); 546 } 547 } 548 549 delete container[name]; 550 } 551 552 } 553 554 555 }; 556 557 }(); 558 559 YAHOO.register("profiler", YAHOO.tool.Profiler, {version: "2.9.0", build: "2800"}); 560 561 }, '2.9.0' ,{"requires": ["yui2-yahoo"]});
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |