| /* |
| Copyright (c) 2008, Yahoo! Inc. All rights reserved. |
| Code licensed under the BSD License: |
| http://developer.yahoo.net/yui/license.txt |
| version: 2.6.0 |
| */ |
| YAHOO.namespace("tool"); |
| |
| /** |
| * The YUI JavaScript profiler. |
| * @module profiler |
| * @namespace YAHOO.tool |
| * @requires yahoo |
| */ |
| |
| /** |
| * Profiles functions in JavaScript. |
| * @namespace YAHOO.tool |
| * @class Profiler |
| * @static |
| */ |
| YAHOO.tool.Profiler = { |
| |
| //------------------------------------------------------------------------- |
| // Private Properties |
| //------------------------------------------------------------------------- |
| |
| /** |
| * Container object on which to put the original unprofiled methods. |
| * @type Object |
| * @private |
| * @static |
| * @property _container |
| */ |
| _container : new Object(), |
| |
| /** |
| * Call information for functions. |
| * @type Object |
| * @private |
| * @static |
| * @property _report |
| */ |
| _report : new Object(), |
| |
| //------------------------------------------------------------------------- |
| // Private Methods |
| //------------------------------------------------------------------------- |
| |
| /** |
| * Called when a method ends execution. Marks the start and end time of the |
| * method so it can calculate how long the function took to execute. Also |
| * updates min/max/avg calculations for the function. |
| * @param {String} name The name of the function to mark as stopped. |
| * @param {int} duration The number of milliseconds it took the function to |
| * execute. |
| * @return {Void} |
| * @private |
| * @static |
| */ |
| _saveData : function (name /*:String*/, duration /*:int*/){ |
| |
| //get the function data |
| var functionData /*:Object*/ = this._report[name]; |
| |
| //increment the calls |
| functionData.calls++; |
| functionData.points.push(duration); |
| |
| //if it's already been called at least once, do more complex calculations |
| if (functionData.calls > 1) { |
| functionData.avg = ((functionData.avg*(functionData.calls-1))+duration)/functionData.calls; |
| functionData.min = Math.min(functionData.min, duration); |
| functionData.max = Math.max(functionData.max, duration); |
| } else { |
| functionData.avg = duration; |
| functionData.min = duration; |
| functionData.max = duration; |
| } |
| |
| }, |
| |
| //------------------------------------------------------------------------- |
| // Reporting Methods |
| //------------------------------------------------------------------------- |
| |
| /** |
| * Returns the average amount of time (in milliseconds) that the function |
| * with the given name takes to execute. |
| * @param {String} name The name of the function whose data should be returned. |
| * If an object type method, it should be 'constructor.prototype.methodName'; |
| * a normal object method would just be 'object.methodName'. |
| * @return {float} The average time it takes the function to execute. |
| * @static |
| */ |
| getAverage : function (name /*:String*/) /*:float*/ { |
| return this._report[name].avg; |
| }, |
| |
| /** |
| * Returns the number of times that the given function has been called. |
| * @param {String} name The name of the function whose data should be returned. |
| * @return {int} The number of times the function was called. |
| * @static |
| */ |
| getCallCount : function (name /*:String*/) /*:int*/ { |
| return this._report[name].calls; |
| }, |
| |
| /** |
| * Returns the maximum amount of time (in milliseconds) that the function |
| * with the given name takes to execute. |
| * @param {String} name The name of the function whose data should be returned. |
| * If an object type method, it should be 'constructor.prototype.methodName'; |
| * a normal object method would just be 'object.methodName'. |
| * @return {float} The maximum time it takes the function to execute. |
| */ |
| getMax : function (name /*:String*/) /*:int*/ { |
| return this._report[name].max; |
| }, |
| |
| /** |
| * Returns the minimum amount of time (in milliseconds) that the function |
| * with the given name takes to execute. |
| * @param {String} name The name of the function whose data should be returned. |
| * If an object type method, it should be 'constructor.prototype.methodName'; |
| * a normal object method would just be 'object.methodName'. |
| * @return {float} The minimum time it takes the function to execute. |
| */ |
| getMin : function (name /*:String*/) /*:int*/ { |
| return this._report[name].min; |
| }, |
| |
| /** |
| * Returns an object containing profiling data for a single function. |
| * The object has an entry for min, max, avg, calls, and points). |
| * @return {Object} An object containing profile data for a given function. |
| * @static |
| */ |
| getFunctionReport : function (name /*:String*/) /*:Object*/ { |
| return this._report[name]; |
| }, |
| |
| /** |
| * Returns an object containing profiling data for all of the functions |
| * that were profiled. The object has an entry for each function and |
| * returns all information (min, max, average, calls, etc.) for each |
| * function. |
| * @return {Object} An object containing all profile data. |
| * @static |
| */ |
| getFullReport : function (filter /*:Function*/) /*:Object*/ { |
| filter = filter || function(){return true;}; |
| |
| if (YAHOO.lang.isFunction(filter)) { |
| var report = {}; |
| |
| for (var name in this._report){ |
| if (filter(this._report[name])){ |
| report[name] = this._report[name]; |
| } |
| } |
| |
| return report; |
| } |
| }, |
| |
| //------------------------------------------------------------------------- |
| // Profiling Methods |
| //------------------------------------------------------------------------- |
| |
| /** |
| * Sets up a constructor for profiling, including all properties and methods on the prototype. |
| * @param {string} name The fully-qualified name of the function including namespace information. |
| * @param {Object} owner (Optional) The object that owns the function (namespace or containing object). |
| * @return {Void} |
| * @static |
| */ |
| registerConstructor : function (name /*:String*/, owner /*:Object*/) /*:Void*/ { |
| this.registerFunction(name, owner, true); |
| }, |
| |
| /** |
| * Sets up a function for profiling. It essentially overwrites the function with one |
| * that has instrumentation data. This method also creates an entry for the function |
| * in the profile report. The original function is stored on the _container object. |
| * @param {String} name The full name of the function including namespacing. This |
| * is the name of the function that is stored in the report. |
| * @param {Object} owner (Optional) The object that owns the function. If the function |
| * isn't global then this argument is required. This could be the namespace that |
| * the function belongs to, such as YAHOO.util.Dom, or the object on which it's |
| * a method. |
| * @return {Void} |
| * @method registerFunction |
| */ |
| registerFunction : function(name /*:String*/, owner /*:Object*/, registerPrototype /*:Boolean*/) /*:Void*/{ |
| |
| //figure out the function name without namespacing |
| var funcName /*:String*/ = (name.indexOf(".") > -1 ? name.substring(name.lastIndexOf(".")+1) : name); |
| if (!YAHOO.lang.isObject(owner)){ |
| owner = eval(name.substring(0, name.lastIndexOf("."))); |
| } |
| |
| //get the method and prototype |
| var method /*:Function*/ = owner[funcName]; |
| var prototype /*:Object*/ = method.prototype; |
| |
| //see if the method has already been registered |
| if (YAHOO.lang.isFunction(method) && !method.__yuiProfiled){ |
| |
| //create a new slot for the original method |
| this._container[name] = method; |
| |
| //replace the function with the profiling one |
| owner[funcName] = function () { |
| |
| var start = new Date(); |
| var retval = method.apply(this, arguments); |
| var stop = new Date(); |
| |
| YAHOO.tool.Profiler._saveData(name, stop-start); |
| |
| return retval; |
| |
| }; |
| |
| //copy the function properties over |
| YAHOO.lang.augmentObject(owner[funcName], method); |
| owner[funcName].__yuiProfiled = true; |
| owner[funcName].prototype = prototype; |
| this._container[name].__yuiOwner = owner; |
| this._container[name].__yuiFuncName = funcName; |
| |
| //register prototype if necessary |
| if (registerPrototype) { |
| this.registerObject(name + ".prototype", prototype); |
| } |
| |
| //store function information |
| this._report[name] = { |
| calls: 0, |
| max: 0, |
| min: 0, |
| avg: 0, |
| points: [] |
| }; |
| } |
| |
| return method; |
| |
| }, |
| |
| |
| /** |
| * Sets up an object for profiling. It takes the object and looks for functions. |
| * When a function is found, registerMethod() is called on it. If set to recrusive |
| * mode, it will also setup objects found inside of this object for profiling, |
| * using the same methodology. |
| * @param {String} name The name of the object to profile (shows up in report). |
| * @param {Object} owner (Optional) The object represented by the name. |
| * @param {Boolean} recurse (Optional) Determines if subobject methods are also profiled. |
| * @return {Void} |
| * @static |
| */ |
| registerObject : function (name /*:String*/, object /*:Object*/, recurse /*:Boolean*/) /*:Void*/{ |
| |
| //get the object |
| object = (YAHOO.lang.isObject(object) ? object : eval(name)); |
| |
| //save the object |
| this._container[name] = object; |
| |
| for (var prop in object) { |
| if (typeof object[prop] == "function"){ |
| if (prop != "constructor" && prop != "superclass"){ //don't do constructor or superclass, it's recursive |
| this.registerFunction(name + "." + prop, object); |
| } |
| } else if (typeof object[prop] == "object" && recurse){ |
| this.registerObject(name + "." + prop, object[prop], recurse); |
| } |
| } |
| |
| }, |
| |
| /** |
| * Removes a constructor function from profiling. Reverses the registerConstructor() method. |
| * @param {String} name The full name of the function including namespacing. This |
| * is the name of the function that is stored in the report. |
| * @return {Void} |
| * @method unregisterFunction |
| */ |
| unregisterConstructor : function(name /*:String*/) /*:Void*/{ |
| |
| //see if the method has been registered |
| if (YAHOO.lang.isFunction(this._container[name])){ |
| |
| //get original data |
| //var owner /*:Object*/ = this._container[name].__yuiOwner; |
| //var funcName /*:String*/ = this._container[name].__yuiFuncName; |
| //delete this._container[name].__yuiOwner; |
| //delete this._container[name].__yuiFuncName; |
| |
| //replace instrumented function |
| //owner[funcName] = this._container[name]; |
| //delete this._container[name]; |
| this.unregisterFunction(name, true); |
| |
| } |
| |
| |
| }, |
| |
| /** |
| * Removes function from profiling. Reverses the registerFunction() method. |
| * @param {String} name The full name of the function including namespacing. This |
| * is the name of the function that is stored in the report. |
| * @return {Void} |
| * @method unregisterFunction |
| */ |
| unregisterFunction : function(name /*:String*/, unregisterPrototype /*:Boolean*/) /*:Void*/{ |
| |
| //see if the method has been registered |
| if (YAHOO.lang.isFunction(this._container[name])){ |
| |
| //check to see if you should unregister the prototype |
| if (unregisterPrototype){ |
| this.unregisterObject(name + ".prototype", this._container[name].prototype); |
| } |
| |
| //get original data |
| var owner /*:Object*/ = this._container[name].__yuiOwner; |
| var funcName /*:String*/ = this._container[name].__yuiFuncName; |
| delete this._container[name].__yuiOwner; |
| delete this._container[name].__yuiFuncName; |
| |
| //replace instrumented function |
| owner[funcName] = this._container[name]; |
| |
| //delete supporting information |
| delete this._container[name]; |
| delete this._report[name]; |
| |
| } |
| |
| |
| }, |
| |
| /** |
| * Unregisters an object for profiling. It takes the object and looks for functions. |
| * When a function is found, unregisterMethod() is called on it. If set to recrusive |
| * mode, it will also unregister objects found inside of this object, |
| * using the same methodology. |
| * @param {String} name The name of the object to unregister. |
| * @param {Boolean} recurse (Optional) Determines if subobject methods should also be |
| * unregistered. |
| * @return {Void} |
| * @static |
| */ |
| unregisterObject : function (name /*:String*/, recurse /*:Boolean*/) /*:Void*/{ |
| |
| //get the object |
| if (YAHOO.lang.isObject(this._container[name])){ |
| var object = this._container[name]; |
| |
| for (var prop in object) { |
| if (typeof object[prop] == "function"){ |
| this.unregisterFunction(name + "." + prop); |
| } else if (typeof object[prop] == "object" && recurse){ |
| this.unregisterObject(name + "." + prop, recurse); |
| } |
| } |
| |
| delete this._container[name]; |
| } |
| |
| } |
| |
| |
| }; |
| YAHOO.register("profiler", YAHOO.tool.Profiler, {version: "2.6.0", build: "1321"}); |