Bug 454376 add -lCrun -lCstd for Solaris OS_LIBS, r=bsmedberg
[wine-gecko.git] / tools / footprint / leak-gauge.html
blob34f6afe21059d4131719b9e77f7e7353f2867690
1 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
2 "http://www.w3.org/TR/html4/strict.dtd">
3 <!--
4 vim:sw=4:ts=4:et:
5 ***** BEGIN LICENSE BLOCK *****
6 Version: MPL 1.1/GPL 2.0/LGPL 2.1
8 The contents of this file are subject to the Mozilla Public License Version
9 1.1 (the "License"); you may not use this file except in compliance with
10 the License. You may obtain a copy of the License at
11 http://www.mozilla.org/MPL/
13 Software distributed under the License is distributed on an "AS IS" basis,
14 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
15 for the specific language governing rights and limitations under the
16 License.
18 The Original Code is leak-gauge.pl
20 The Initial Developer of the Original Code is the Mozilla Foundation.
21 Portions created by the Initial Developer are Copyright (C) 2005
22 the Initial Developer. All Rights Reserved.
24 Contributor(s):
25 L. David Baron <dbaron@dbaron.org>, Mozilla Corporation (original author)
27 Alternatively, the contents of this file may be used under the terms of
28 either the GNU General Public License Version 2 or later (the "GPL"), or
29 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 in which case the provisions of the GPL or the LGPL are applicable instead
31 of those above. If you wish to allow use of your version of this file only
32 under the terms of either the GPL or the LGPL, and not to allow others to
33 use your version of this file under the terms of the MPL, indicate your
34 decision by deleting the provisions above and replace them with the notice
35 and other provisions required by the GPL or the LGPL. If you do not delete
36 the provisions above, a recipient may use your version of this file under
37 the terms of any one of the MPL, the GPL or the LGPL.
39 ***** END LICENSE BLOCK *****
40 -->
41 <html lang="en-US">
42 <head>
43 <title>Leak Gauge</title>
45 <style type="text/css">
46 pre { margin: 0; }
47 pre.output { border: medium solid; padding: 1em; margin: 1em; }
48 </style>
49 <script type="text/javascript">
51 function runfile(file) {
52 // A hash of objects (keyed by the first word of the line in the log)
53 // that have two public methods, handle_line and dump (to be called using
54 // call, above), along with any private data they need.
55 var handlers = {
56 "DOMWINDOW": {
57 count: 0,
58 windows: {},
59 handle_line: function(line) {
60 var match = line.match(/^([0-9a-f]*) (\S*)(.*)/);
61 if (match) {
62 var addr = match[1];
63 var verb = match[2];
64 var rest = match[3];
65 if (verb == "created") {
66 var m = rest.match(/ outer=([0-9a-f]*)$/);
67 if (!m)
68 throw "outer expected";
69 this.windows[addr] = { outer: m[1] };
70 ++this.count;
71 } else if (verb == "destroyed") {
72 delete this.windows[addr];
73 } else if (verb == "SetNewDocument") {
74 var m = rest.match(/^ (.*)$/);
75 if (!m)
76 throw "URI expected";
77 this.windows[addr][m[1]] = true;
81 dump: function() {
82 for (var addr in this.windows) {
83 var winobj = this.windows[addr];
84 var outer = winobj.outer;
85 delete winobj.outer;
86 result += "Leaked " + (outer == "0" ? "outer" : "inner") +
87 " window " + addr + " " +
88 (outer == "0" ? "" : "(outer " + outer + ") ") +
89 "at address " + addr + ".\n";
90 for (var uri in winobj) {
91 result += " ... with URI \"" + uri + "\".\n";
95 summary: function() {
96 var len = 0;
97 for (var w in this.windows)
98 ++len;
99 result += 'Leaked ' + len + ' out of ' +
100 this.count + " DOM Windows\n";
103 "DOCUMENT": {
104 count: 0,
105 docs: {},
106 handle_line: function(line) {
107 var match = line.match(/^([0-9a-f]*) (\S*)(.*)/);
108 if (match) {
109 var addr = match[1];
110 var verb = match[2];
111 var rest = match[3];
112 if (verb == "created") {
113 this.docs[addr] = {};
114 ++this.count;
115 } else if (verb == "destroyed") {
116 delete this.docs[addr];
117 } else if (verb == "ResetToURI" ||
118 verb == "StartDocumentLoad") {
119 var m = rest.match(/^ (.*)$/);
120 if (!m)
121 throw "URI expected";
122 var uri = m[1];
123 var doc_info = this.docs[addr];
124 doc_info[uri] = true;
125 if ("nim" in doc_info) {
126 doc_info["nim"][uri] = true;
131 dump: function() {
132 for (var addr in this.docs) {
133 var doc = this.docs[addr];
134 result += "Leaked document at address " + addr + ".\n";
135 for (var uri in doc) {
136 if (uri != "nim") {
137 result += " ... with URI \"" + uri + "\".\n";
142 summary: function() {
143 var len = 0;
144 for (var w in this.docs)
145 ++len;
146 result += 'Leaked ' + len + ' out of ' +
147 this.count + " documents\n";
150 "DOCSHELL": {
151 count: 0,
152 shells: {},
153 handle_line: function(line) {
154 var match = line.match(/^([0-9a-f]*) (\S*)(.*)/);
155 if (match) {
156 var addr = match[1];
157 var verb = match[2];
158 var rest = match[3];
159 if (verb == "created") {
160 this.shells[addr] = {};
161 ++this.count;
162 } else if (verb == "destroyed") {
163 delete this.shells[addr];
164 } else if (verb == "InternalLoad" ||
165 verb == "SetCurrentURI") {
166 var m = rest.match(/^ (.*)$/);
167 if (!m)
168 throw "URI expected";
169 this.shells[addr][m[1]] = true;
173 dump: function() {
174 for (var addr in this.shells) {
175 var doc = this.shells[addr];
176 result += "Leaked docshell at address " + addr + ".\n";
177 for (var uri in doc) {
178 result += " ... which loaded URI \"" + uri + "\".\n";
182 summary: function() {
183 var len = 0;
184 for (var w in this.shells)
185 ++len;
186 result += 'Leaked ' + len + ' out of ' +
187 this.count + " docshells\n";
190 "NODEINFOMANAGER": {
191 count: 0,
192 nims: {},
193 handle_line: function(line) {
194 var match = line.match(/^([0-9a-f]*) (\S*)(.*)/);
195 if (match) {
196 var addr = match[1];
197 var verb = match[2];
198 var rest = match[3];
199 if (verb == "created") {
200 this.nims[addr] = {};
201 ++this.count;
202 } else if (verb == "destroyed") {
203 delete this.nims[addr];
204 } else if (verb == "Init") {
205 var m = rest.match(/^ document=(.*)$/);
206 if (!m)
207 throw "document pointer expected";
208 var nim_info = this.nims[addr];
209 var doc = m[1];
210 if (doc != "0") {
211 var doc_info = handlers["DOCUMENT"].docs[doc];
212 for (var uri in doc_info) {
213 nim_info[uri] = true;
215 doc_info["nim"] = nim_info;
220 dump: function() {
221 for (var addr in this.nims) {
222 var nim = this.nims[addr];
223 result += "Leaked content nodes associated with node info manager at address " + addr + ".\n";
224 for (var uri in nim) {
225 result += " ... with document URI \"" + uri + "\".\n";
229 summary: function() {
230 var len = 0;
231 for (var w in this.nims)
232 ++len;
233 result += 'Leaked content nodes in ' + len + ' out of ' +
234 this.count + " documents\n";
239 var result = "Results of processing log " + file.fileName + " :\n";
241 var contents = file.getAsText("iso-8859-1");
242 var lines = contents.split(/[\r\n]+/);
243 for (var j in lines) {
244 var line = lines[j];
245 // strip off initial "-", thread id, and thread pointer; separate
246 // first word and rest
247 var matches = line.match(/^\-?[0-9]*\[[0-9a-f]*\]: (\S*) (.*)$/);
248 if (matches) {
249 var handler = matches[1];
250 var data = matches[2];
251 if (typeof(handlers[handler]) != "undefined") {
252 handlers[handler].handle_line(data);
257 for (var handler in handlers)
258 handlers[handler].dump();
259 if (result.length)
260 result += "\n";
261 result += "Summary:\n";
262 for (var handler in handlers)
263 handlers[handler].summary();
264 result += "\n";
266 var out = document.createElement("pre");
267 out.className = "output";
268 out.appendChild(document.createTextNode(result));
269 document.body.appendChild(out);
272 function run() {
273 var input = document.getElementById("fileinput");
274 var files = input.files;
275 for (var i = 0; i < files.length; ++i)
276 runfile(files[i]);
277 // So the user can process the same filename again (after
278 // overwriting the log), clear the value on the form input so we
279 // will always get an onchange event.
280 input.value = "";
283 </script>
284 </head>
285 <body>
287 <h1>Leak Gauge</h1>
289 <pre>$Id: leak-gauge.html,v 1.8 2008/02/08 19:55:34 dbaron%dbaron.org Exp $</pre>
291 <p>This script is designed to help testers isolate and simplify testcases
292 for many classes of leaks (those that involve large graphs of core
293 data structures) in Mozilla-based browsers. It is designed to print
294 information about what has leaked by processing a log taken while
295 running the browser. Such a log can be taken over a long session of
296 normal browsing and then the log can be processed to find sites that
297 leak. Once a site is known to leak, the logging can then be repeated
298 to figure out under what conditions the leak occurs.</p>
300 <p>The way to create this log is to set the environment variables:</p>
301 <pre> NSPR_LOG_MODULES=DOMLeak:5,DocumentLeak:5,nsDocShellLeak:5,NodeInfoManagerLeak:5
302 NSPR_LOG_FILE=nspr.log <i>(or any other filename of your choice)</i></pre>
303 <p>in your shell and then run the program.</p>
304 <ul>
305 <li>In a Windows command prompt, set environment variables with
306 <pre> set VAR=value</pre></li>
307 <li> In an sh-based shell such as bash, set environment variables with
308 <pre> export VAR=value</pre></li>
309 <li>In a csh-based shell such as tcsh, set environment variables with
310 <pre> setenv VAR value</pre></li>
311 </ul>
313 <p>Once you have this log from a complete run of the browser (you have
314 to exit; otherwise it will look like everything leaked), you can load
315 this page (be careful not to overwrite the log when starting the browser
316 to load this page) and enter the filename of the log:</p>
318 <p><input type="file" id="fileinput" onchange="run()"></p>
320 <p>Then you'll see the output below, which will tell you which of
321 certain core objects leaked and the URLs associated with those
322 objects.</p>
324 </body>
325 </html>