~launchpad-pqm/lazr-js/toolchain

« back to all changes in this revision

Viewing changes to src-js/lazrjs/yui/profiler/profiler-debug.js

  • Committer: Sidnei da Silva
  • Date: 2009-11-16 00:51:29 UTC
  • mto: This revision was merged to the branch mainline in revision 154.
  • Revision ID: sidnei.da.silva@canonical.com-20091116005129-8ibwjlboa38glaw5
- Improved generation of skin modules and revamped combo service to make it more twisty.

Show diffs side-by-side

added added

removed removed

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