code: def run_memleak_test(bench, iterations, report):
      tracemalloc.start()
  
      starti = min(50, iterations // 2)
      endi = iterations
  
      malloc_arr = np.empty(endi, dtype=np.int64)
      rss_arr = np.empty(endi, dtype=np.int64)
      rss_peaks = np.empty(endi, dtype=np.int64)
      nobjs_arr = np.empty(endi, dtype=np.int64)
      garbage_arr = np.empty(endi, dtype=np.int64)
      open_files_arr = np.empty(endi, dtype=np.int64)
      rss_peak = 0
  
      p = psutil.Process()
  
      for i in range(endi):
          bench()
  
          gc.collect()
  
          rss = p.memory_info().rss
          malloc, peak = tracemalloc.get_traced_memory()
          nobjs = len(gc.get_objects())
          garbage = len(gc.garbage)
          open_files = len(p.open_files())
          print(
              f"{i: 4d}: pymalloc {malloc: 10d}, rss {rss: 10d}, "
              f"nobjs {nobjs: 10d}, garbage {garbage: 4d}, "
              f"files: {open_files: 4d}"
          )
          if i == starti:
              print(f'{" warmup done ":-^86s}')
          malloc_arr[i] = malloc
          rss_arr[i] = rss
          if rss > rss_peak:
              rss_peak = rss
          rss_peaks[i] = rss_peak
          nobjs_arr[i] = nobjs
          garbage_arr[i] = garbage
          open_files_arr[i] = open_files
  
      print(
          "Average memory consumed per loop: {:1.4f} bytes\n".format(
              np.sum(rss_peaks[starti + 1 :] - rss_peaks[starti:-1])
              / (endi - starti)
          )
      )
  
      from matplotlib import pyplot as plt
      from matplotlib.ticker import EngFormatter
  
      bytes_formatter = EngFormatter(unit="B")
      fig, (ax1, ax2, ax3) = plt.subplots(3)
      for ax in (ax1, ax2, ax3):
          ax.axvline(starti, linestyle="--", color="k")
      ax1b = ax1.twinx()
      ax1b.yaxis.set_major_formatter(bytes_formatter)
      ax1.plot(malloc_arr, "C0")
      ax1b.plot(rss_arr, "C1", label="rss")
      ax1b.plot(rss_peaks, "C1", linestyle="--", label="rss max")
      ax1.set_ylabel("pymalloc", color="C0")
      ax1b.set_ylabel("rss", color="C1")
      ax1b.legend()
  
      ax2b = ax2.twinx()
      ax2.plot(nobjs_arr, "C0")
      ax2b.plot(garbage_arr, "C1")
      ax2.set_ylabel("total objects", color="C0")
      ax2b.set_ylabel("garbage objects", color="C1")
  
      ax3.plot(open_files_arr)
      ax3.set_ylabel("open file handles")
  
      if not report.endswith(".pdf"):
          report = report + ".pdf"
      fig.tight_layout()
      fig.savefig(report, format="pdf")
  
file_path: matplotlib/tools/memleak.py
imports: import gc
  from io import BytesIO
  import tracemalloc
  import numpy
label_desc: Use image node_id 1 for calling a global function with example usage: run_memleak_test(bench, iterations, report) without return types