2
Copyright (c) 2009, Yahoo! Inc. All rights reserved.
3
Code licensed under the BSD License:
4
http://developer.yahoo.net/yui/license.txt
7
YAHOO.namespace("tool");
10
* The YUI JavaScript profiler.
12
* @namespace YAHOO.tool
17
* Profiles functions in JavaScript.
18
* @namespace YAHOO.tool
22
YAHOO.tool.Profiler = {
24
//-------------------------------------------------------------------------
26
//-------------------------------------------------------------------------
29
* Container object on which to put the original unprofiled methods.
33
* @property _container
35
_container : new Object(),
38
* Call information for functions.
44
_report : new Object(),
46
//-------------------------------------------------------------------------
48
//-------------------------------------------------------------------------
51
* Called when a method ends execution. Marks the start and end time of the
52
* method so it can calculate how long the function took to execute. Also
53
* updates min/max/avg calculations for the function.
54
* @param {String} name The name of the function to mark as stopped.
55
* @param {int} duration The number of milliseconds it took the function to
61
_saveData : function (name /*:String*/, duration /*:int*/){
63
//get the function data
64
var functionData /*:Object*/ = this._report[name];
68
functionData.points.push(duration);
70
//if it's already been called at least once, do more complex calculations
71
if (functionData.calls > 1) {
72
functionData.avg = ((functionData.avg*(functionData.calls-1))+duration)/functionData.calls;
73
functionData.min = Math.min(functionData.min, duration);
74
functionData.max = Math.max(functionData.max, duration);
76
functionData.avg = duration;
77
functionData.min = duration;
78
functionData.max = duration;
83
//-------------------------------------------------------------------------
85
//-------------------------------------------------------------------------
88
* Returns the average amount of time (in milliseconds) that the function
89
* with the given name takes to execute.
90
* @param {String} name The name of the function whose data should be returned.
91
* If an object type method, it should be 'constructor.prototype.methodName';
92
* a normal object method would just be 'object.methodName'.
93
* @return {float} The average time it takes the function to execute.
96
getAverage : function (name /*:String*/) /*:float*/ {
97
return this._report[name].avg;
101
* Returns the number of times that the given function has been called.
102
* @param {String} name The name of the function whose data should be returned.
103
* @return {int} The number of times the function was called.
106
getCallCount : function (name /*:String*/) /*:int*/ {
107
return this._report[name].calls;
111
* Returns the maximum amount of time (in milliseconds) that the function
112
* with the given name takes to execute.
113
* @param {String} name The name of the function whose data should be returned.
114
* If an object type method, it should be 'constructor.prototype.methodName';
115
* a normal object method would just be 'object.methodName'.
116
* @return {float} The maximum time it takes the function to execute.
118
getMax : function (name /*:String*/) /*:int*/ {
119
return this._report[name].max;
123
* Returns the minimum amount of time (in milliseconds) that the function
124
* with the given name takes to execute.
125
* @param {String} name The name of the function whose data should be returned.
126
* If an object type method, it should be 'constructor.prototype.methodName';
127
* a normal object method would just be 'object.methodName'.
128
* @return {float} The minimum time it takes the function to execute.
130
getMin : function (name /*:String*/) /*:int*/ {
131
return this._report[name].min;
135
* Returns an object containing profiling data for a single function.
136
* The object has an entry for min, max, avg, calls, and points).
137
* @return {Object} An object containing profile data for a given function.
140
getFunctionReport : function (name /*:String*/) /*:Object*/ {
141
return this._report[name];
145
* Returns an object containing profiling data for all of the functions
146
* that were profiled. The object has an entry for each function and
147
* returns all information (min, max, average, calls, etc.) for each
149
* @return {Object} An object containing all profile data.
152
getFullReport : function (filter /*:Function*/) /*:Object*/ {
153
filter = filter || function(){return true;};
155
if (YAHOO.lang.isFunction(filter)) {
158
for (var name in this._report){
159
if (filter(this._report[name])){
160
report[name] = this._report[name];
168
//-------------------------------------------------------------------------
170
//-------------------------------------------------------------------------
173
* Sets up a constructor for profiling, including all properties and methods on the prototype.
174
* @param {string} name The fully-qualified name of the function including namespace information.
175
* @param {Object} owner (Optional) The object that owns the function (namespace or containing object).
179
registerConstructor : function (name /*:String*/, owner /*:Object*/) /*:Void*/ {
180
this.registerFunction(name, owner, true);
184
* Sets up a function for profiling. It essentially overwrites the function with one
185
* that has instrumentation data. This method also creates an entry for the function
186
* in the profile report. The original function is stored on the _container object.
187
* @param {String} name The full name of the function including namespacing. This
188
* is the name of the function that is stored in the report.
189
* @param {Object} owner (Optional) The object that owns the function. If the function
190
* isn't global then this argument is required. This could be the namespace that
191
* the function belongs to, such as YAHOO.util.Dom, or the object on which it's
194
* @method registerFunction
196
registerFunction : function(name /*:String*/, owner /*:Object*/, registerPrototype /*:Boolean*/) /*:Void*/{
198
//figure out the function name without namespacing
199
var funcName /*:String*/ = (name.indexOf(".") > -1 ? name.substring(name.lastIndexOf(".")+1) : name);
200
if (!YAHOO.lang.isObject(owner)){
201
owner = eval(name.substring(0, name.lastIndexOf(".")));
204
//get the method and prototype
205
var method /*:Function*/ = owner[funcName];
206
var prototype /*:Object*/ = method.prototype;
208
//see if the method has already been registered
209
if (YAHOO.lang.isFunction(method) && !method.__yuiProfiled){
211
//create a new slot for the original method
212
this._container[name] = method;
214
//replace the function with the profiling one
215
owner[funcName] = function () {
217
var start = new Date();
218
var retval = method.apply(this, arguments);
219
var stop = new Date();
221
YAHOO.tool.Profiler._saveData(name, stop-start);
227
//copy the function properties over
228
YAHOO.lang.augmentObject(owner[funcName], method);
229
owner[funcName].__yuiProfiled = true;
230
owner[funcName].prototype = prototype;
231
this._container[name].__yuiOwner = owner;
232
this._container[name].__yuiFuncName = funcName;
234
//register prototype if necessary
235
if (registerPrototype) {
236
this.registerObject(name + ".prototype", prototype);
239
//store function information
240
this._report[name] = {
255
* Sets up an object for profiling. It takes the object and looks for functions.
256
* When a function is found, registerMethod() is called on it. If set to recrusive
257
* mode, it will also setup objects found inside of this object for profiling,
258
* using the same methodology.
259
* @param {String} name The name of the object to profile (shows up in report).
260
* @param {Object} owner (Optional) The object represented by the name.
261
* @param {Boolean} recurse (Optional) Determines if subobject methods are also profiled.
265
registerObject : function (name /*:String*/, object /*:Object*/, recurse /*:Boolean*/) /*:Void*/{
268
object = (YAHOO.lang.isObject(object) ? object : eval(name));
271
this._container[name] = object;
273
for (var prop in object) {
274
if (typeof object[prop] == "function"){
275
if (prop != "constructor" && prop != "superclass"){ //don't do constructor or superclass, it's recursive
276
this.registerFunction(name + "." + prop, object);
278
} else if (typeof object[prop] == "object" && recurse){
279
this.registerObject(name + "." + prop, object[prop], recurse);
286
* Removes a constructor function from profiling. Reverses the registerConstructor() method.
287
* @param {String} name The full name of the function including namespacing. This
288
* is the name of the function that is stored in the report.
290
* @method unregisterFunction
292
unregisterConstructor : function(name /*:String*/) /*:Void*/{
294
//see if the method has been registered
295
if (YAHOO.lang.isFunction(this._container[name])){
298
//var owner /*:Object*/ = this._container[name].__yuiOwner;
299
//var funcName /*:String*/ = this._container[name].__yuiFuncName;
300
//delete this._container[name].__yuiOwner;
301
//delete this._container[name].__yuiFuncName;
303
//replace instrumented function
304
//owner[funcName] = this._container[name];
305
//delete this._container[name];
306
this.unregisterFunction(name, true);
314
* Removes function from profiling. Reverses the registerFunction() method.
315
* @param {String} name The full name of the function including namespacing. This
316
* is the name of the function that is stored in the report.
318
* @method unregisterFunction
320
unregisterFunction : function(name /*:String*/, unregisterPrototype /*:Boolean*/) /*:Void*/{
322
//see if the method has been registered
323
if (YAHOO.lang.isFunction(this._container[name])){
325
//check to see if you should unregister the prototype
326
if (unregisterPrototype){
327
this.unregisterObject(name + ".prototype", this._container[name].prototype);
331
var owner /*:Object*/ = this._container[name].__yuiOwner;
332
var funcName /*:String*/ = this._container[name].__yuiFuncName;
333
delete this._container[name].__yuiOwner;
334
delete this._container[name].__yuiFuncName;
336
//replace instrumented function
337
owner[funcName] = this._container[name];
339
//delete supporting information
340
delete this._container[name];
341
delete this._report[name];
349
* Unregisters an object for profiling. It takes the object and looks for functions.
350
* When a function is found, unregisterMethod() is called on it. If set to recrusive
351
* mode, it will also unregister objects found inside of this object,
352
* using the same methodology.
353
* @param {String} name The name of the object to unregister.
354
* @param {Boolean} recurse (Optional) Determines if subobject methods should also be
359
unregisterObject : function (name /*:String*/, recurse /*:Boolean*/) /*:Void*/{
362
if (YAHOO.lang.isObject(this._container[name])){
363
var object = this._container[name];
365
for (var prop in object) {
366
if (typeof object[prop] == "function"){
367
this.unregisterFunction(name + "." + prop);
368
} else if (typeof object[prop] == "object" && recurse){
369
this.unregisterObject(name + "." + prop, recurse);
373
delete this._container[name];
380
YAHOO.register("profiler", YAHOO.tool.Profiler, {version: "2.7.0", build: "1799"});