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