Skip to content

Commit f4fefe7

Browse files
committed
document the memory leak test instead of the visualvm query
1 parent 51b66c4 commit f4fefe7

File tree

1 file changed

+9
-64
lines changed

1 file changed

+9
-64
lines changed

docs/contributor/CONTRIBUTING.md

Lines changed: 9 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -298,67 +298,12 @@ default configuration of a single Python context (as is used when running the
298298
launcher). For better sharing of warmup and where absolutely best peak
299299
performance is not needed, contexts can be configured with a shared engine and
300300
the ASTs will be shared across contexts. However, that implies we *must* not
301-
store any user objects strongly in the ASTs. Here is a query to find any such
302-
leaks where a PythonObject is reacheable from any kind of Truffle AST Node
303-
subinstance in VisualVM:
304-
305-
findLeaks("com.oracle.graal.python.builtins.objects.object.PythonObject", "com.oracle.truffle.api.nodes.Node")
306-
307-
function findLeaks(to, from) {
308-
var objs = heap.objects(to, true)
309-
var leaks = []
310-
var path = []
311-
var cutOffPath = false
312-
313-
while (objs.hasMoreElements() && leaks.length < 100) {
314-
var o = objs.nextElement()
315-
path = []
316-
cutOffPath = false
317-
if (isReferencedFromAtMaxDepth(o, 20)) {
318-
if (!cutOffPath) {
319-
leaks.push(o)
320-
}
321-
}
322-
}
323-
return leaks
324-
325-
function isReferencedFromAtMaxDepth(obj, limit) {
326-
var refs = referrers(obj)
327-
while (refs.hasMoreElements()) {
328-
var o = refs.nextElement()
329-
var refClass = classof(o)
330-
var cutOffHere = false
331-
while (refClass != null) {
332-
if (refClass.name == from) {
333-
leaks.push(classof(o).name)
334-
return true
335-
} else if (refClass.name == "java.lang.ref.WeakReference" ||
336-
refClass.name == "java.lang.ref.SoftReference" ||
337-
refClass.name == "java.lang.ref.PhantomReference") {
338-
// any weak reference is fine
339-
return false;
340-
} else if (refClass.name == to) {
341-
// we have found another `to` object along the path, use this one as the shorter path
342-
cutOffHere = true
343-
}
344-
refClass = refClass.superclass
345-
}
346-
if (limit > 0) {
347-
if (isReferencedFromAtMaxDepth(o, limit - 1)) {
348-
if (!cutOffPath) {
349-
if (cutOffHere) {
350-
cutOffPath = true
351-
leaks.push(o)
352-
} else {
353-
leaks.push(classof(o).name)
354-
}
355-
}
356-
return true
357-
}
358-
}
359-
}
360-
return false
361-
}
362-
}
363-
364-
Running such a query on a multi-context heap should yield no results.
301+
store any user objects strongly in the ASTs. We test that we have no
302+
PythonObjects alive after a Context is closed that are run as part of our JUnit
303+
tests. These can be run by themselves, for example, like so:
304+
305+
$ mx python-leak-test --lang python --shared-engine --code 'import site, json' --forbidden-class com.oracle.graal.python.builtins.objects.object.PythonObject --keep-dump
306+
307+
The `--keep-dump` option will print the heapdump location and leave the file
308+
there rather than deleting it. It can then be opened for example with VisualVM
309+
to check for the paths of any leaked object, if there are any.

0 commit comments

Comments
 (0)