Skip to content

Commit 05c347f

Browse files
committed
Add a new memleak script that does everything
This replaces our 4 memleak scripts with one that is able to test any backend, with or without plot content, and with or without interactive mode. The calculation of average increase per iteration has been fixed. Before, it assumed the increase was monotonically increasing, when in fact it flucuates quite a bit. Therefore, it now calculates the difference between each pair of results and averages that. Also, the results are stored in pre-allocated Numpy arrays rather than Python lists to avoid including the increasing size of the Python lists in the results.
1 parent 94e94e3 commit 05c347f

File tree

5 files changed

+122
-245
lines changed

5 files changed

+122
-245
lines changed

unit/agg_memleak.py

-62
This file was deleted.

unit/memleak.py

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#!/usr/bin/env python
2+
3+
from __future__ import print_function
4+
5+
import gc
6+
import tracemalloc
7+
8+
import numpy as np
9+
10+
11+
def run_memleak_test(bench, iterations, report):
12+
from matplotlib.cbook import report_memory
13+
14+
tracemalloc.start()
15+
16+
starti = min(10, iterations / 2)
17+
endi = iterations
18+
19+
malloc_arr = np.empty((endi,), dtype=np.int64)
20+
rss_arr = np.empty((endi,), dtype=np.int64)
21+
nobjs_arr = np.empty((endi,), dtype=np.int64)
22+
garbage_arr = np.empty((endi,), dtype=np.int64)
23+
24+
for i in range(endi):
25+
bench()
26+
27+
gc.collect()
28+
rss = report_memory()
29+
malloc, peak = tracemalloc.get_traced_memory()
30+
nobjs = len(gc.get_objects())
31+
garbage = len(gc.garbage)
32+
print("{0: 4d}: pymalloc {1: 10d}, rss {2: 10d}, nobjs {3: 10d}, garbage {4: 10d}".format(
33+
i, malloc, rss, nobjs, garbage))
34+
35+
malloc_arr[i] = malloc
36+
rss_arr[i] = rss
37+
nobjs_arr[i] = nobjs
38+
garbage_arr[i] = garbage
39+
40+
print('Average memory consumed per loop: %1.4f bytes\n' %
41+
(np.sum(rss_arr[starti+1:] - rss_arr[starti:-1]) / float(endi - starti)))
42+
43+
from matplotlib import pyplot as plt
44+
fig, (ax1, ax2) = plt.subplots(2)
45+
ax3 = ax1.twinx()
46+
ax1.plot(malloc_arr[5:], 'r')
47+
ax3.plot(rss_arr[5:], 'b')
48+
ax1.set_ylabel('pymalloc', color='r')
49+
ax3.set_ylabel('rss', color='b')
50+
51+
ax4 = ax2.twinx()
52+
ax2.plot(nobjs_arr[5:], 'r')
53+
ax4.plot(garbage_arr[5:], 'b')
54+
ax2.set_ylabel('total objects', color='r')
55+
ax4.set_ylabel('garbage objects', color='b')
56+
57+
if not report.endswith('.pdf'):
58+
report = report + '.pdf'
59+
fig.savefig(report, format='pdf')
60+
61+
62+
class MemleakTest(object):
63+
def __init__(self, empty):
64+
self.empty = empty
65+
66+
def __call__(self):
67+
import matplotlib.pyplot as plt
68+
69+
fig = plt.figure(1)
70+
71+
if not self.empty:
72+
t1 = np.arange(0.0, 2.0, 0.01)
73+
y1 = np.sin(2 * np.pi * t1)
74+
y2 = np.random.rand(len(t1))
75+
X = np.random.rand(50, 50)
76+
77+
ax = fig.add_subplot(221)
78+
ax.plot(t1, y1, '-')
79+
ax.plot(t1, y2, 's')
80+
81+
ax = fig.add_subplot(222)
82+
ax.imshow(X)
83+
84+
ax = fig.add_subplot(223)
85+
ax.scatter(np.random.rand(50), np.random.rand(50),
86+
s=100 * np.random.rand(50), c=np.random.rand(50))
87+
88+
ax = fig.add_subplot(224)
89+
ax.pcolor(10 * np.random.rand(50, 50))
90+
91+
fig.savefig('tmp', dpi=75)
92+
plt.close(1)
93+
94+
95+
if __name__ == '__main__':
96+
import argparse
97+
98+
parser = argparse.ArgumentParser('Run memory leak tests')
99+
parser.add_argument('backend', type=str, nargs=1,
100+
help='backend to test')
101+
parser.add_argument('iterations', type=int, nargs=1,
102+
help='number of iterations')
103+
parser.add_argument('report', type=str, nargs=1,
104+
help='filename to save report')
105+
parser.add_argument('--empty', action='store_true',
106+
help="Don't plot any content, just test creating "
107+
"and destroying figures")
108+
parser.add_argument('--interactive', action='store_true',
109+
help="Turn on interactive mode to actually open "
110+
"windows. Only works with some GUI backends.")
111+
112+
113+
args = parser.parse_args()
114+
115+
import matplotlib
116+
matplotlib.use(args.backend[0])
117+
118+
if args.interactive:
119+
from matplotlib import pyplot as plt
120+
plt.ion()
121+
122+
run_memleak_test(MemleakTest(args.empty), args.iterations[0], args.report[0])

unit/memleak_gui.py

-103
This file was deleted.

unit/memleak_hawaii3.py

-61
This file was deleted.

unit/memleak_nongui.py

-19
This file was deleted.

0 commit comments

Comments
 (0)