1 <!DOCTYPE html PUBLIC
"-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
4 This Source Code Form is subject to the terms of the Mozilla Public
5 - License, v. 2.0. If a copy of the MPL was not distributed with this
6 - file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 <meta charset=
"UTF-8" />
11 <title>Leak Gauge
</title>
13 <style type=
"text/css">
24 function runfile(file
) {
25 var result
= "Results of processing log " + file
.fileName
+ " :\n";
27 var fileReader
= new FileReader();
28 fileReader
.onload = function (e
) {
29 runContents(result
, e
.target
.result
);
31 fileReader
.readAsText(file
, "iso-8859-1");
34 function runContents(result
, contents
) {
35 // A hash of objects (keyed by the first word of the line in the log)
36 // that have two public methods, handle_line and dump (to be called using
37 // call, above), along with any private data they need.
43 var match
= line
.match(/^([0-9a-f]*) (\S*)(.*)/);
48 if (verb
== "created") {
49 let m
= rest
.match(/ outer
=([0-9a
-f
]*)$/);
50 if (!m
) throw new Error("outer expected");
51 this.windows
[addr
] = { outer
: m
[1] };
53 } else if (verb
== "destroyed") {
54 delete this.windows
[addr
];
55 } else if (verb
== "SetNewDocument") {
56 let m
= rest
.match(/^ (.*)$/);
57 if (!m
) throw new Error("URI expected");
58 this.windows
[addr
][m
[1]] = true;
63 for (var addr
in this.windows
) {
64 var winobj
= this.windows
[addr
];
65 var outer
= winobj
.outer
;
69 (outer
== "0" ? "outer" : "inner") +
73 (outer
== "0" ? "" : "(outer " + outer
+ ") ") +
77 for (var uri
in winobj
) {
78 result
+= ' ... with URI "' + uri
+ '".\n';
85 Object
.keys(this.windows
).length
+
95 var match
= line
.match(/^([0-9a-f]*) (\S*)(.*)/);
100 if (verb
== "created") {
101 this.docs
[addr
] = {};
103 } else if (verb
== "destroyed") {
104 delete this.docs
[addr
];
106 verb
== "ResetToURI" ||
107 verb
== "StartDocumentLoad"
109 var m
= rest
.match(/^ (.*)$/);
110 if (!m
) throw new Error("URI expected");
112 var doc_info
= this.docs
[addr
];
113 doc_info
[uri
] = true;
114 if ("nim" in doc_info
) {
115 doc_info
.nim
[uri
] = true;
121 for (var addr
in this.docs
) {
122 var doc
= this.docs
[addr
];
123 result
+= "Leaked document at address " + addr
+ ".\n";
124 for (var uri
in doc
) {
126 result
+= ' ... with URI "' + uri
+ '".\n';
134 Object
.keys(this.docs
).length
+
144 var match
= line
.match(/^([0-9a-f]*) (\S*)(.*)/);
149 if (verb
== "created") {
150 this.shells
[addr
] = {};
152 } else if (verb
== "destroyed") {
153 delete this.shells
[addr
];
154 } else if (verb
== "InternalLoad" || verb
== "SetCurrentURI") {
155 var m
= rest
.match(/^ (.*)$/);
156 if (!m
) throw new Error("URI expected");
157 this.shells
[addr
][m
[1]] = true;
162 for (var addr
in this.shells
) {
163 var doc
= this.shells
[addr
];
164 result
+= "Leaked docshell at address " + addr
+ ".\n";
165 for (var uri
in doc
) {
166 result
+= ' ... which loaded URI "' + uri
+ '".\n';
173 Object
.keys(this.shells
).length
+
183 var match
= line
.match(/^([0-9a-f]*) (\S*)(.*)/);
188 if (verb
== "created") {
189 this.nims
[addr
] = {};
191 } else if (verb
== "destroyed") {
192 delete this.nims
[addr
];
193 } else if (verb
== "Init") {
194 var m
= rest
.match(/^ document=(.*)$/);
195 if (!m
) throw new Error("document pointer expected");
196 var nim_info
= this.nims
[addr
];
199 var doc_info
= handlers
.DOCUMENT
.docs
[doc
];
200 for (var uri
in doc_info
) {
201 nim_info
[uri
] = true;
203 doc_info
.nim
= nim_info
;
209 for (var addr
in this.nims
) {
210 var nim
= this.nims
[addr
];
212 "Leaked content nodes associated with node info manager at address " +
215 for (var uri
in nim
) {
216 result
+= ' ... with document URI "' + uri
+ '".\n';
222 "Leaked content nodes in " +
223 Object
.keys(this.nims
).length
+
231 var lines
= contents
.split(/[\r\n]+/);
232 for (var j
in lines
) {
234 // strip off initial "-", thread id, and thread pointer; separate
235 // first word and rest
236 var matches
= line
.match(/^\-?[0-9]*\[[0-9a-f]*\]: (\S*) (.*)$/);
238 let handler
= matches
[1];
239 var data
= matches
[2];
240 if (typeof handlers
[handler
] != "undefined") {
241 handlers
[handler
].handle_line(data
);
246 for (let handler
in handlers
) handlers
[handler
].dump();
247 if (result
.length
) result
+= "\n";
248 result
+= "Summary:\n";
249 for (let handler
in handlers
) handlers
[handler
].summary();
252 var out
= document
.createElement("pre");
253 out
.className
= "output";
254 out
.appendChild(document
.createTextNode(result
));
255 document
.body
.appendChild(out
);
259 var input
= document
.getElementById("fileinput");
260 var files
= input
.files
;
261 for (var i
= 0; i
< files
.length
; ++i
) runfile(files
[i
]);
262 // So the user can process the same filename again (after
263 // overwriting the log), clear the value on the form input so we
264 // will always get an onchange event.
273 $Id: leak-gauge.html,v
1.8 2008/
02/
08 19:
55:
34 dbaron%dbaron.org Exp $
</pre
277 This script is designed to help testers isolate and simplify testcases for
278 many classes of leaks (those that involve large graphs of core data
279 structures) in Mozilla-based browsers. It is designed to print information
280 about what has leaked by processing a log taken while running the browser.
281 Such a log can be taken over a long session of normal browsing and then
282 the log can be processed to find sites that leak. Once a site is known to
283 leak, the logging can then be repeated to figure out under what conditions
287 <p>The way to create this log is to set the environment variables:
</p>
288 <pre> MOZ_LOG=DOMLeak:
5,DocumentLeak:
5,nsDocShellLeak:
5,NodeInfoManagerLeak:
5
289 MOZ_LOG_FILE=nspr.log
<i>(or any other filename of your choice)
</i></pre>
290 <p>in your shell and then run the program.
</p>
293 In a Windows command prompt, set environment variables with
294 <pre> set VAR=value
</pre>
297 In an sh-based shell such as bash, set environment variables with
298 <pre> export VAR=value
</pre>
301 In a csh-based shell such as tcsh, set environment variables with
302 <pre> setenv VAR value
</pre>
307 Once you have this log from a complete run of the browser (you have to
308 exit; otherwise it will look like everything leaked), you can load this
309 page (be careful not to overwrite the log when starting the browser to
310 load this page) and enter the filename of the log:
313 <p><input type=
"file" id=
"fileinput" onchange=
"run()" /></p>
316 Then you'll see the output below, which will tell you which of certain
317 core objects leaked and the URLs associated with those objects.