Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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"]});