<br><div class="gmail_quote">On Wed, Mar 16, 2011 at 8:38 AM, Amit Dev <span dir="ltr"><<a href="mailto:amitdev@gmail.com">amitdev@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
I'm observing a strange memory usage pattern with strings. Consider<br>
the following session. Idea is to create a list which holds some<br>
strings so that cumulative characters in the list is 100MB.<br>
<br>
>>> l = []<br>
>>> for i in xrange(100000):<br>
...  l.append(str(i) * (1000/len(str(i))))<br>
<br>
This uses around 100MB of memory as expected and 'del l' will clear that.<br>
<br>
<br>
>>> for i in xrange(20000):<br>
...  l.append(str(i) * (5000/len(str(i))))<br>
<br>
This is using 165MB of memory. I really don't understand where the<br>
additional memory usage is coming from.<br>
<br>
If I reduce the string size, it remains high till it reaches around<br>
1000. In that case it is back to 100MB usage.<br>
<br>
Python 2.6.4 on FreeBSD.<br>
<br>
Regards,<br>
Amit<br>
<font color="#888888">--<br>
<a href="http://mail.python.org/mailman/listinfo/python-list" target="_blank">http://mail.python.org/mailman/listinfo/python-list</a><br>
</font></blockquote></div><br>On Python 2.6.6 on Ubuntu 10.10:<br><br>$ cat pmu<br>#!/usr/bin/python<br><br>import os<br>import sys<br><br>list_ = []<br><br>if sys.argv[1] == '--first':<br>        for i in xrange(100000):<br>
                list_.append(str(i) * (1000/len(str(i))))<br>elif sys.argv[1] == '--second':<br>        for i in xrange(20000):<br>                list_.append(str(i) * (5000/len(str(i))))<br>else:<br>        sys.stderr.write('%s: Illegal sys.argv[1]\n' % sys.argv[0])<br>
        sys.exit(1)<br><br>os.system("ps aux | egrep '\<%d\>|^USER\>'" % os.getpid())<br><br>dstromberg-laptop-dstromberg:~/src/python-mem-use i686-pc-linux-gnu 10916 - above cmd done 2011 Wed Mar 16 02:38 PM<br>
<br>$ make<br>./pmu --first<br>USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND<br>1000     11063  0.0  3.4 110212 104436 pts/5   S+   14:38   0:00 /usr/bin/python ./pmu --first<br>1000     11064  0.0  0.0   1896   512 pts/5    S+   14:38   0:00 sh -c ps aux | egrep '\<11063\>|^USER\>'<br>
1000     11066  0.0  0.0   4012   740 pts/5    S+   14:38   0:00 egrep \<11063\>|^USER\><br>./pmu --second<br>USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND<br>1000     11067 13.0  3.3 107540 101536 pts/5   S+   14:38   0:00 /usr/bin/python ./pmu --second<br>
1000     11068  0.0  0.0   1896   508 pts/5    S+   14:38   0:00 sh -c ps aux | egrep '\<11067\>|^USER\>'<br>1000     11070  0.0  0.0   4012   740 pts/5    S+   14:38   0:00 egrep \<11067\>|^USER\><br>
dstromberg-laptop-dstromberg:~/src/python-mem-use i686-pc-linux-gnu 10916 - above cmd done 2011 Wed Mar 16 02:38 PM<br><br>So on Python 2.6.6 + Ubuntu 10.10, the second is actually a little smaller than the first.<br><br>
Some issues you might ponder:<br>1) Does FreeBSD's malloc/free know how to free unused memory pages in the middle of the heap (using mmap games), or does it only sbrk() down when the end of the heap becomes unused, or does it never sbrk() back down at all?   I've heard various *ix's fall into one of these 3 groups in releasing unused pages.<br>
<br>2) It mijght be just an issue of how frequently the interpreter garbage collects; you could try adjusting this; check out the gc module.  Note that it's often faster not to collect at every conceivable opportunity, but this tends to add up the bytes pretty quickly in some scripts - for a while, until the next collection.  So your memory use pattern will often end up looking like a bit of a sawtooth function.<br>
<br>3) If you need strict memory use guarantees, you might be better off with a language that's closer to the metal, like C - something that isn't garbage collected is one parameter to consider.  If you already have something in CPython, then Cython might help; Cython allows you to use C datastructures from a dialect of Python.<br>
<br><br>