1 <!DOCTYPE html PUBLIC
"-//W3C//DTD HTML 4.01//EN"
2 "http://www.w3.org/TR/html4/strict.dtd">
5 This Source Code Form is subject to the terms of the Mozilla Public
6 - License, v. 2.0. If a copy of the MPL was not distributed with this
7 - file, You can obtain one at http://mozilla.org/MPL/2.0/.
11 <title>Leak Gauge
</title>
13 <style type=
"text/css">
15 pre
.output
{ border: medium solid
; padding: 1em; margin: 1em; }
17 <script type=
"text/javascript">
19 function runFile(file
) {
20 var result
= "Results of processing log " + file
.fileName
+ " :\n";
22 var fileReader
= new FileReader();
23 fileReader
.onload = function(e
)
25 runContents(result
, e
.target
.result
);
27 fileReader
.readAsText(file
, "iso-8859-1");
30 function runContents(result
, contents
) {
31 // A hash of objects (keyed by the first word of the line in the log)
32 // that have two public methods, handle_line and dump (to be called using
33 // call, above), along with any private data they need.
38 handle_line: function(line
) {
39 var match
= line
.match(/^([0-9a-f]*) (\S*)(.*)/);
44 if (verb
== "created") {
45 var m
= rest
.match(/ outer
=([0-9a
-f
]*)$/);
47 throw "outer expected";
48 this.windows
[addr
] = { outer
: m
[1] };
50 } else if (verb
== "destroyed") {
51 delete this.windows
[addr
];
52 } else if (verb
== "SetNewDocument") {
53 var m
= rest
.match(/^ (.*)$/);
56 this.windows
[addr
][m
[1]] = true;
61 for (var addr
in this.windows
) {
62 var winobj
= this.windows
[addr
];
63 var outer
= winobj
.outer
;
65 result
+= "Leaked " + (outer
== "0" ? "outer" : "inner") +
66 " window " + addr
+ " " +
67 (outer
== "0" ? "" : "(outer " + outer
+ ") ") +
68 "at address " + addr
+ ".\n";
69 for (var uri
in winobj
) {
70 result
+= " ... with URI \"" + uri
+ "\".\n";
76 for (var w
in this.windows
)
78 result
+= 'Leaked ' + len
+ ' out of ' +
79 this.count
+ " DOM Windows\n";
85 handle_line: function(line
) {
86 var match
= line
.match(/^([0-9a-f]*) (\S*)(.*)/);
91 if (verb
== "created") {
94 } else if (verb
== "destroyed") {
95 delete this.docs
[addr
];
96 } else if (verb
== "ResetToURI" ||
97 verb
== "StartDocumentLoad") {
98 var m
= rest
.match(/^ (.*)$/);
100 throw "URI expected";
102 var doc_info
= this.docs
[addr
];
103 doc_info
[uri
] = true;
104 if ("nim" in doc_info
) {
105 doc_info
["nim"][uri
] = true;
111 for (var addr
in this.docs
) {
112 var doc
= this.docs
[addr
];
113 result
+= "Leaked document at address " + addr
+ ".\n";
114 for (var uri
in doc
) {
116 result
+= " ... with URI \"" + uri
+ "\".\n";
121 summary: function() {
123 for (var w
in this.docs
)
125 result
+= 'Leaked ' + len
+ ' out of ' +
126 this.count
+ " documents\n";
132 handle_line: function(line
) {
133 var match
= line
.match(/^([0-9a-f]*) (\S*)(.*)/);
138 if (verb
== "created") {
139 this.shells
[addr
] = {};
141 } else if (verb
== "destroyed") {
142 delete this.shells
[addr
];
143 } else if (verb
== "InternalLoad" ||
144 verb
== "SetCurrentURI") {
145 var m
= rest
.match(/^ (.*)$/);
147 throw "URI expected";
148 this.shells
[addr
][m
[1]] = true;
153 for (var addr
in this.shells
) {
154 var doc
= this.shells
[addr
];
155 result
+= "Leaked docshell at address " + addr
+ ".\n";
156 for (var uri
in doc
) {
157 result
+= " ... which loaded URI \"" + uri
+ "\".\n";
161 summary: function() {
163 for (var w
in this.shells
)
165 result
+= 'Leaked ' + len
+ ' out of ' +
166 this.count
+ " docshells\n";
172 handle_line: function(line
) {
173 var match
= line
.match(/^([0-9a-f]*) (\S*)(.*)/);
178 if (verb
== "created") {
179 this.nims
[addr
] = {};
181 } else if (verb
== "destroyed") {
182 delete this.nims
[addr
];
183 } else if (verb
== "Init") {
184 var m
= rest
.match(/^ document=(.*)$/);
186 throw "document pointer expected";
187 var nim_info
= this.nims
[addr
];
190 var doc_info
= handlers
["DOCUMENT"].docs
[doc
];
191 for (var uri
in doc_info
) {
192 nim_info
[uri
] = true;
194 doc_info
["nim"] = nim_info
;
200 for (var addr
in this.nims
) {
201 var nim
= this.nims
[addr
];
202 result
+= "Leaked content nodes associated with node info manager at address " + addr
+ ".\n";
203 for (var uri
in nim
) {
204 result
+= " ... with document URI \"" + uri
+ "\".\n";
208 summary: function() {
210 for (var w
in this.nims
)
212 result
+= 'Leaked content nodes in ' + len
+ ' out of ' +
213 this.count
+ " documents\n";
218 var lines
= contents
.split(/[\r\n]+/);
219 for (var j
in lines
) {
221 // strip off initial "-", thread id, and thread pointer; separate
222 // first word and rest
223 var matches
= line
.match(/^\-?[0-9]*\[[0-9a-f]*\]: (\S*) (.*)$/);
225 var handler
= matches
[1];
226 var data
= matches
[2];
227 if (typeof(handlers
[handler
]) != "undefined") {
228 handlers
[handler
].handle_line(data
);
233 for (var handler
in handlers
)
234 handlers
[handler
].dump();
237 result
+= "Summary:\n";
238 for (var handler
in handlers
)
239 handlers
[handler
].summary();
242 var out
= document
.createElement("pre");
243 out
.className
= "output";
244 out
.appendChild(document
.createTextNode(result
));
245 document
.body
.appendChild(out
);
249 var input
= document
.getElementById("fileinput");
250 var files
= input
.files
;
251 for (var i
= 0; i
< files
.length
; ++i
)
253 // So the user can process the same filename again (after
254 // overwriting the log), clear the value on the form input so we
255 // will always get an onchange event.
265 <pre>$Id: leak-gauge.html,v
1.8 2008/
02/
08 19:
55:
34 dbaron%dbaron.org Exp $
</pre>
267 <p>This script is designed to help testers isolate and simplify testcases
268 for many classes of leaks (those that involve large graphs of core
269 data structures) in Mozilla-based browsers. It is designed to print
270 information about what has leaked by processing a log taken while
271 running the browser. Such a log can be taken over a long session of
272 normal browsing and then the log can be processed to find sites that
273 leak. Once a site is known to leak, the logging can then be repeated
274 to figure out under what conditions the leak occurs.
</p>
276 <p>The way to create this log is to set the environment variables:
</p>
277 <pre> NSPR_LOG_MODULES=DOMLeak:
5,DocumentLeak:
5,nsDocShellLeak:
5,NodeInfoManagerLeak:
5
278 NSPR_LOG_FILE=nspr.log
<i>(or any other filename of your choice)
</i></pre>
279 <p>in your shell and then run the program.
</p>
281 <li>In a Windows command prompt, set environment variables with
282 <pre> set VAR=value
</pre></li>
283 <li> In an sh-based shell such as bash, set environment variables with
284 <pre> export VAR=value
</pre></li>
285 <li>In a csh-based shell such as tcsh, set environment variables with
286 <pre> setenv VAR value
</pre></li>
289 <p>Once you have this log from a complete run of the browser (you have
290 to exit; otherwise it will look like everything leaked), you can load
291 this page (be careful not to overwrite the log when starting the browser
292 to load this page) and enter the filename of the log:
</p>
294 <p><input type=
"file" id=
"fileinput" onchange=
"run()"></p>
296 <p>Then you'll see the output below, which will tell you which of
297 certain core objects leaked and the URLs associated with those