-
Notifications
You must be signed in to change notification settings - Fork 9
/
garbagegraph.py
79 lines (62 loc) · 2.41 KB
/
garbagegraph.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
from pympler.refgraph import ReferenceGraph
from pympler.util.stringutils import trunc, pp
import sys
import gc
__all__ = ['GarbageGraph', 'start_debug_garbage', 'end_debug_garbage']
class GarbageGraph(ReferenceGraph):
"""
The ``GarbageGraph`` is a ``ReferenceGraph`` that illustrates the objects building
reference cycles. The garbage collector is switched to debug mode (all
identified garbage is stored in `gc.garbage`) and the garbage collector is
invoked. The collected objects are then illustrated in a directed graph.
Large graphs can be reduced to the actual cycles by passing ``reduce=True`` to
the constructor.
It is recommended to disable the garbage collector when using the
``GarbageGraph``.
>>> from pympler.garbagegraph import GarbageGraph, start_debug_garbage
>>> start_debug_garbage()
>>> l = []
>>> l.append(l)
>>> del l
>>> gb = GarbageGraph()
>>> gb.render('garbage.eps')
True
"""
def __init__(self, reduce=False, collectable=True):
"""
Initialize the GarbageGraph with the objects identified by the garbage
collector. If `collectable` is true, every reference cycle is recorded.
Otherwise only uncollectable objects are reported.
"""
if collectable:
gc.set_debug(gc.DEBUG_SAVEALL)
else:
gc.set_debug(0)
gc.collect()
ReferenceGraph.__init__(self, gc.garbage, reduce)
def print_stats(self, stream=None):
"""
Log annotated garbage objects to console or file.
:param stream: open file, uses sys.stdout if not given
"""
if not stream: # pragma: no cover
stream = sys.stdout
self.metadata.sort(key=lambda x: -x.size)
stream.write('%-10s %8s %-12s %-46s\n' % ('id', 'size', 'type', 'representation'))
for g in self.metadata:
stream.write('0x%08x %8d %-12s %-46s\n' % (g.id, g.size, trunc(g.type, 12),
trunc(g.str, 46)))
stream.write('Garbage: %8d collected objects (%s in cycles): %12s\n' % \
(self.count, self.num_in_cycles, pp(self.total_size)))
def start_debug_garbage():
"""
Turn off garbage collector to analyze *collectable* reference cycles.
"""
gc.collect()
gc.disable()
def end_debug_garbage():
"""
Turn garbage collection on and disable debug output.
"""
gc.set_debug(0)
gc.enable()