title: Memory is not released after function calls in python
body: <p>I have been playing with <code>memory_profiler</code> for some time and got this interesting but confusing results from the small program below:</p>
  
  <pre class="lang-python prettyprint-override"><code>import pandas as pd
  import numpy as np
  
  @profile
  def f(p):
      tmp = []
      for _, frame in p.iteritems():
          tmp.append([list(record) for record in frame.to_records(index=False)])
  
  # initialize a list of pandas panels
  lp = []
  for j in xrange(50):
      d = {}
      for i in xrange(50):
          df = pd.DataFrame(np.random.randn(200, 50))
          d[i] = df
      lp.append(pd.Panel(d))
  
  # execution (iteration)
  for panel in lp:
      f(panel)
  </code></pre>
  
  <p>Then if I use memory_profiler's mprof to analyze the memory usage during runtime, <code>mprof run test.py</code> without any other parameters, I get this:
  <img src="https://i.stack.imgur.com/Fi8KN.png" alt="memory_profiling_results_1.png">. </p>
  
  <p>There seems to be memory unreleased after each function call f().</p>
  
  <p><code>tmp</code> is just a local list and should be reassigned and memory reallocated each time f() is called. Obviously there is some discrepancy here in the graph attached. I know that python has its own memory management blocks and also has free list for int and other types, and <code>gc.collect()</code> should do the magic. It turns out that explicit <code>gc.collect()</code> doesn't work. (Maybe because we are working with pandas objects, panels and frames? I don't know.)</p>
  
  <p>The most confusing part is, I don't change or modify any variable in <code>f()</code>. All it does is just put some list representation copies in a local list. Therefore python doesn't need to make a copy of anything. Then why and how does this happen?</p>
  
  <p>=================</p>
  
  <p>Some other observations:</p>
  
  <p>1) If I call <code>f()</code> with <code>f(panel.copy())</code> (last line of code), passing the copy instead of the original object reference, I have a totally different memory usage result: <img src="https://i.stack.imgur.com/sCgXp.png" alt="memory_profiling_results_2.png">. Is python that smart to tell that this value passed is a copy so that it could do some internal tricks to release the memory after each function call?</p>
  
  <p>2) I think it might be because of <code>df.to_records()</code>. Well if I change it to <code>frame.values</code>, I would get similar flat memory curve, just like <code>memory_profiling_results_2.png</code> shown above, during the iteration (Although I do need <code>to_records()</code> because it maintains the column dtype, while <code>.values</code> messes the dtypes up). But I looked into frame.py's implementation on <code>to_records()</code>. I don't see why it would hold on the memory out there, while <code>.values</code> would work just fine.</p>
  
  <p>I am running the program on Windows, with python 2.7.8, memory_profiler 0.43 and psutil 5.0.1.</p>