| // Copyright 2007 The Closure Library Authors. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS-IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| /** |
| * @fileoverview Definition of the GcDiagnostics class. |
| * |
| */ |
| |
| goog.provide('goog.debug.GcDiagnostics'); |
| |
| goog.require('goog.debug.Trace'); |
| goog.require('goog.log'); |
| goog.require('goog.userAgent'); |
| |
| |
| |
| /** |
| * Class used for singleton goog.debug.GcDiagnostics. Used to hook into |
| * the L2 ActiveX controller to profile garbage collection information in IE. |
| * Can be used in combination with tracers (goog.debug.Trace), to provide object |
| * allocation counts from within the tracers or used alone by invoking start and |
| * stop. |
| * |
| * See http://go/l2binary for the install. |
| * TODO(user): Move the L2 installer somewhere more general. |
| * @constructor |
| * @private |
| */ |
| goog.debug.GcDiagnostics_ = function() {}; |
| |
| |
| /** |
| * Install the GcDiagnostics tool. |
| */ |
| goog.debug.GcDiagnostics_.prototype.install = function() { |
| if (goog.userAgent.IE) { |
| /** @preserveTry */ |
| try { |
| var l2Helper = new ActiveXObject('L2.NativeHelper'); |
| |
| // If using tracers, use the higher precision timer provided by L2. |
| if (goog.debug.Trace_) { |
| goog.debug.Trace_.now = function() { |
| return l2Helper['getMilliSeconds'](); |
| }; |
| } |
| |
| if (l2Helper['gcTracer']) { |
| l2Helper['gcTracer']['installGcTracing'](); |
| this.gcTracer_ = l2Helper['gcTracer']; |
| if (goog.debug.Trace) { |
| // If tracers are in use, register the gcTracer so that per tracer |
| // allocations are recorded. |
| goog.debug.Trace.setGcTracer(this.gcTracer_); |
| } |
| } |
| goog.log.info(this.logger_, 'Installed L2 native helper'); |
| } catch (e) { |
| goog.log.info(this.logger_, 'Failed to install L2 native helper: ' + e); |
| } |
| } |
| }; |
| |
| |
| /** |
| * Logger for the gcDiagnotics |
| * @type {goog.log.Logger} |
| * @private |
| */ |
| goog.debug.GcDiagnostics_.prototype.logger_ = |
| goog.log.getLogger('goog.debug.GcDiagnostics'); |
| |
| |
| /** |
| * Starts recording garbage collection information. If a trace is already in |
| * progress, it is ended. |
| */ |
| goog.debug.GcDiagnostics_.prototype.start = function() { |
| if (this.gcTracer_) { |
| if (this.gcTracer_['isTracing']()) { |
| this.gcTracer_['endGcTracing'](); |
| } |
| this.gcTracer_['startGcTracing'](); |
| } |
| }; |
| |
| |
| /** |
| * Stops recording garbage collection information. Logs details on the garbage |
| * collections that occurred between start and stop. If tracers are in use, |
| * adds comments where each GC occurs. |
| */ |
| goog.debug.GcDiagnostics_.prototype.stop = function() { |
| if (this.gcTracer_ && this.gcTracer_['isTracing']()) { |
| var gcTracer = this.gcTracer_; |
| this.gcTracer_['endGcTracing'](); |
| |
| var numGCs = gcTracer['getNumTraces'](); |
| goog.log.info(this.logger_, '*********GC TRACE*********'); |
| goog.log.info(this.logger_, 'GC ran ' + numGCs + ' times.'); |
| var totalTime = 0; |
| for (var i = 0; i < numGCs; i++) { |
| var trace = gcTracer['getTrace'](i); |
| |
| var msStart = trace['gcStartTime']; |
| var msElapsed = trace['gcElapsedTime']; |
| |
| var msRounded = Math.round(msElapsed * 10) / 10; |
| var s = 'GC ' + i + ': ' + msRounded + ' ms, ' + |
| 'numVValAlloc=' + trace['numVValAlloc'] + ', ' + |
| 'numVarAlloc=' + trace['numVarAlloc'] + ', ' + |
| 'numBytesSysAlloc=' + trace['numBytesSysAlloc']; |
| if (goog.debug.Trace) { |
| goog.debug.Trace.addComment(s, null, msStart); |
| } |
| goog.log.info(this.logger_, s); |
| totalTime += msElapsed; |
| } |
| if (goog.debug.Trace) { |
| goog.debug.Trace.addComment('Total GC time was ' + totalTime + ' ms.'); |
| } |
| goog.log.info(this.logger_, 'Total GC time was ' + totalTime + ' ms.'); |
| goog.log.info(this.logger_, '*********GC TRACE*********'); |
| } |
| }; |
| |
| |
| /** |
| * Singleton GcDiagnostics object |
| * @type {goog.debug.GcDiagnostics_} |
| */ |
| goog.debug.GcDiagnostics = new goog.debug.GcDiagnostics_(); |