|
| 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]) |
0 commit comments