<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>
<channel>
	<title>Comments on: Malloc free space not reclaimed</title>
	<atom:link href="http://kevin.sb.org/2007/07/05/malloc-free-space-not-reclaimed/feed/" rel="self" type="application/rss+xml" />
	<link>http://kevin.sb.org/2007/07/05/malloc-free-space-not-reclaimed/</link>
	<description>The occasional view into my life</description>
	<pubDate>Fri, 04 Jul 2008 00:19:44 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
		<item>
		<title>By: Adam Strzelecki</title>
		<link>http://kevin.sb.org/2007/07/05/malloc-free-space-not-reclaimed/#comment-658</link>
		<dc:creator>Adam Strzelecki</dc:creator>
		<pubDate>Tue, 20 May 2008 13:40:15 +0000</pubDate>
		<guid isPermaLink="false">c9c139cd-075a-4abd-a159-8c73c5065991#comment-658</guid>
		<description>There's actually one allocator &lt;b&gt;ptmalloc&lt;/b&gt; http://www.malloc.de/en/index.html that reclaims the memory for small blocks. I've tested also &lt;b&gt;Hoard&lt;/b&gt; but it seems it only grows the memory. But with &lt;b&gt;ptmalloc&lt;/b&gt; simple program below that never gave back 160MB when running default OSX allocator, now dropped to 512KB after &lt;i&gt;Freeing...&lt;/i&gt; loop! BTW. &lt;b&gt;ptmalloc&lt;/b&gt; is used by &lt;b&gt;GNU libc&lt;/b&gt;.


#include "stdio.h"
#include "stdlib.h"
#include "string.h"

int main(int argc, char const *argv[])
{
	char b[4*1024], c = 0;
	void *p[4*10*1024];
	size_t i, len = sizeof(b)/sizeof(b[0]);
	
	printf("Preparing buffer...\n");
	for(i = 0; i &#60; sizeof(b)/sizeof(b[0]); ++i)
	{
		b[i] = c + 'a';
		c = (c + 1) % 30;
	}

	printf("Allocating...\n");
	for(i = 0; i &#60; sizeof(p)/sizeof(p[0]); ++i)
	{
		p[i] = malloc(len);
		memcpy(p[i], b, len);
	}
	printf("Press any key...\n");
	getchar();

	printf("Freing...\n");
	for(i = 0; i &#60; sizeof(p)/sizeof(p[0]); ++i)
		free(p[i]);
	printf("Press any key...\n");
	getchar();

	return 0;
}</description>
		<content:encoded><![CDATA[	<p>There&#8217;s actually one allocator <b>ptmalloc</b> <a href="http://www.malloc.de/en/index.html" rel="nofollow">http://www.malloc.de/en/index.html</a> that reclaims the memory for small blocks. I&#8217;ve tested also <b>Hoard</b> but it seems it only grows the memory. But with <b>ptmalloc</b> simple program below that never gave back 160MB when running default OSX allocator, now dropped to 512KB after <i>Freeing&#8230;</i> loop! BTW. <b>ptmalloc</b> is used by <b>GNU libc</b>.</p>
	<p>#include &#8220;stdio.h&#8221;
#include &#8220;stdlib.h&#8221;
#include &#8220;string.h&#8221;</p>
	<p>int main(int argc, char const *argv[])<br />
{<br />
char b[4*1024], c = 0;<br />
void *p[4*10*1024];<br />
size_t i, len = sizeof(b)/sizeof(b<sup><a href="#fn774763673486d6ca013243">0</a></sup>);</p>
	<p>printf(&#8220;Preparing buffer&#8230;\n&#8221;);<br />
for(i = 0; i < sizeof(b)/sizeof(b<sup><a href="#fn774763673486d6ca013243">0</a>); ++i)<br />
{<br />
b[i] = c + &#8216;a&#8217;;<br />
c = (c + 1) % 30;<br />
}</p>
	<p>printf(&#8220;Allocating&#8230;\n&#8221;);<br />
for(i = 0; i < sizeof(p)/sizeof(p<sup><a href="#fn774763673486d6ca013243">0</a>); ++i)<br />
{<br />
p[i] = malloc(len);<br />
memcpy(p[i], b, len);<br />
}<br />
printf(&#8220;Press any key&#8230;\n&#8221;);<br />
getchar();</p>
	<p>printf(&#8220;Freing&#8230;\n&#8221;);<br />
for(i = 0; i < sizeof(p)/sizeof(p<sup><a href="#fn774763673486d6ca013243">0</a>); ++i)<br />
free(p[i]);<br />
printf(&#8220;Press any key&#8230;\n&#8221;);<br />
getchar();</p>
	<p>return 0;<br />
}</p>

 ]]></content:encoded>
	</item>
	<item>
		<title>By: Ankur</title>
		<link>http://kevin.sb.org/2007/07/05/malloc-free-space-not-reclaimed/#comment-426</link>
		<dc:creator>Ankur</dc:creator>
		<pubDate>Thu, 10 Apr 2008 06:26:34 +0000</pubDate>
		<guid isPermaLink="false">c9c139cd-075a-4abd-a159-8c73c5065991#comment-426</guid>
		<description>&lt;blockquote&gt;Right now Quicksilver is using roughly 235MB of Real Memory.&lt;/blockquote&gt;

Wow. Turning off unused plugins and catalog entries can help there. My (admittedly heavily modded) QS sits between 5 - 12 MB of real memory usage.</description>
		<content:encoded><![CDATA[<blockquote>Right now Quicksilver is using roughly 235MB of Real Memory.</blockquote>
	<p>Wow. Turning off unused plugins and catalog entries can help there. My (admittedly heavily modded) QS sits between 5 &#8211; 12 MB of real memory usage.</p>

 ]]></content:encoded>
	</item>
	<item>
		<title>By: Kevin Lyda</title>
		<link>http://kevin.sb.org/2007/07/05/malloc-free-space-not-reclaimed/#comment-294</link>
		<dc:creator>Kevin Lyda</dc:creator>
		<pubDate>Wed, 02 Jan 2008 05:18:35 +0000</pubDate>
		<guid isPermaLink="false">c9c139cd-075a-4abd-a159-8c73c5065991#comment-294</guid>
		<description>I'm not exactly sure why on OS X, but generally on unix free()s don't reduce the process size. It just marks the memory as unused for future malloc calls to reclaim.</description>
		<content:encoded><![CDATA[	<p>I&#8217;m not exactly sure why on OS X, but generally on unix free()s don&#8217;t reduce the process size. It just marks the memory as unused for future malloc calls to reclaim.</p>

 ]]></content:encoded>
	</item>
	<item>
		<title>By: http://toba.ath.cx:724/blog/</title>
		<link>http://kevin.sb.org/2007/07/05/malloc-free-space-not-reclaimed/#comment-285</link>
		<dc:creator>http://toba.ath.cx:724/blog/</dc:creator>
		<pubDate>Wed, 14 Nov 2007 17:12:52 +0000</pubDate>
		<guid isPermaLink="false">c9c139cd-075a-4abd-a159-8c73c5065991#comment-285</guid>
		<description>Used memory fragmentation - the system can't reclaim the memory unless the entire page is unused, IIRC.</description>
		<content:encoded><![CDATA[	<p>Used memory fragmentation &#8211; the system can&#8217;t reclaim the memory unless the entire page is unused, IIRC.</p>

 ]]></content:encoded>
	</item>
	<item>
		<title>By: Adonis</title>
		<link>http://kevin.sb.org/2007/07/05/malloc-free-space-not-reclaimed/#comment-278</link>
		<dc:creator>Adonis</dc:creator>
		<pubDate>Mon, 01 Oct 2007 17:52:48 +0000</pubDate>
		<guid isPermaLink="false">c9c139cd-075a-4abd-a159-8c73c5065991#comment-278</guid>
		<description>@Kevin:
Thanks for your blog entry! I finally get my answer to one of my long-standing questions.

@Ryan:
Thanks for the in-depth explanation! I've been having this hunch about OS X for at least a year now and never delved deep enough into it to find the answers!

@Paul.G:
If you see this post, could you explain the second part of your reply? (I understand that relying on the kernel to do the work would be slower, but not the grinding to a halt... but what do you mean by "issues with different shared libraries"? what issues are you referring to?)</description>
		<content:encoded><![CDATA[	<p>@Kevin:<br />
Thanks for your blog entry! I finally get my answer to one of my long-standing questions.</p>
	<p>@Ryan:<br />
Thanks for the in-depth explanation! I&#8217;ve been having this hunch about OS X for at least a year now and never delved deep enough into it to find the answers!</p>
	<p>@Paul.G:<br />
If you see this post, could you explain the second part of your reply? (I understand that relying on the kernel to do the work would be slower, but not the grinding to a halt&#8230; but what do you mean by &#8220;issues with different shared libraries&#8221;? what issues are you referring to?)</p>

 ]]></content:encoded>
	</item>
	<item>
		<title>By: Paul G</title>
		<link>http://kevin.sb.org/2007/07/05/malloc-free-space-not-reclaimed/#comment-270</link>
		<dc:creator>Paul G</dc:creator>
		<pubDate>Fri, 07 Sep 2007 20:04:52 +0000</pubDate>
		<guid isPermaLink="false">c9c139cd-075a-4abd-a159-8c73c5065991#comment-270</guid>
		<description>Well, if malloc didn't do this, it might be a lot slower and you'd be surprised how that might really cause many applications to grind to a halt.  Also, by going against one system malloc, there are fewer issues with different shared libraries allocating and disposing of memory (note: this can lead to bad programming practices ;-).  I suppose that background garbage collection might be a possibility?</description>
		<content:encoded><![CDATA[	<p>Well, if malloc didn&#8217;t do this, it might be a lot slower and you&#8217;d be surprised how that might really cause many applications to grind to a halt.  Also, by going against one system malloc, there are fewer issues with different shared libraries allocating and disposing of memory (note: this can lead to bad programming practices ;-).  I suppose that background garbage collection might be a possibility?</p>

 ]]></content:encoded>
	</item>
	<item>
		<title>By: Paul G</title>
		<link>http://kevin.sb.org/2007/07/05/malloc-free-space-not-reclaimed/#comment-269</link>
		<dc:creator>Paul G</dc:creator>
		<pubDate>Fri, 07 Sep 2007 20:04:09 +0000</pubDate>
		<guid isPermaLink="false">c9c139cd-075a-4abd-a159-8c73c5065991#comment-269</guid>
		<description>Well, if malloc didn't do this, it might be a lot slower and you'd be surprised how that might really cause many applications to grind to a halt.  Also, by going against one system malloc, there are fewer issues with different shared libraries allocating and disposing of memory (note: this can lead to bad programming practices ;-).  I suppose that background garbage collection might be a possibility?</description>
		<content:encoded><![CDATA[	<p>Well, if malloc didn&#8217;t do this, it might be a lot slower and you&#8217;d be surprised how that might really cause many applications to grind to a halt.  Also, by going against one system malloc, there are fewer issues with different shared libraries allocating and disposing of memory (note: this can lead to bad programming practices ;-).  I suppose that background garbage collection might be a possibility?</p>

 ]]></content:encoded>
	</item>
	<item>
		<title>By: Paul G.</title>
		<link>http://kevin.sb.org/2007/07/05/malloc-free-space-not-reclaimed/#comment-268</link>
		<dc:creator>Paul G.</dc:creator>
		<pubDate>Fri, 07 Sep 2007 20:02:29 +0000</pubDate>
		<guid isPermaLink="false">c9c139cd-075a-4abd-a159-8c73c5065991#comment-268</guid>
		<description>Well, if malloc didn't do this, it might be a lot slower and you'd be surprised how that might really cause many applications to grind to a halt.  Also, by going against one system malloc, there are fewer issues with different shared libraries allocating and disposing of memory (note: this can lead to bad programming practices ;-).  I suppose that background garbage collection might be a possibility?</description>
		<content:encoded><![CDATA[	<p>Well, if malloc didn&#8217;t do this, it might be a lot slower and you&#8217;d be surprised how that might really cause many applications to grind to a halt.  Also, by going against one system malloc, there are fewer issues with different shared libraries allocating and disposing of memory (note: this can lead to bad programming practices ;-).  I suppose that background garbage collection might be a possibility?</p>

 ]]></content:encoded>
	</item>
	<item>
		<title>By: itistoday</title>
		<link>http://kevin.sb.org/2007/07/05/malloc-free-space-not-reclaimed/#comment-250</link>
		<dc:creator>itistoday</dc:creator>
		<pubDate>Tue, 17 Jul 2007 09:32:21 +0000</pubDate>
		<guid isPermaLink="false">c9c139cd-075a-4abd-a159-8c73c5065991#comment-250</guid>
		<description>Because apple stupidly implemented their malloc system.  For tiny allocations the freed blocks are put on a linked list so that when the program asks for a small block again it can quickly pull them off the list instead of asking the kernel to allocate a new block.  This speeds up performance but because Apple apparently didn't implement a way for this list of freed blocks to be freed, it will just grow in size as the program runs.</description>
		<content:encoded><![CDATA[	<p>Because apple stupidly implemented their malloc system.  For tiny allocations the freed blocks are put on a linked list so that when the program asks for a small block again it can quickly pull them off the list instead of asking the kernel to allocate a new block.  This speeds up performance but because Apple apparently didn&#8217;t implement a way for this list of freed blocks to be freed, it will just grow in size as the program runs.</p>

 ]]></content:encoded>
	</item>
	<item>
		<title>By: Ryan Brown</title>
		<link>http://kevin.sb.org/2007/07/05/malloc-free-space-not-reclaimed/#comment-247</link>
		<dc:creator>Ryan Brown</dc:creator>
		<pubDate>Fri, 06 Jul 2007 22:04:04 +0000</pubDate>
		<guid isPermaLink="false">c9c139cd-075a-4abd-a159-8c73c5065991#comment-247</guid>
		<description>In general, most Unix systems do not return malloced memory to the system when freed (although there are exceptions for large allocations). On OS X allocations take place in one of four categories: tiny (1 - 496 byes), small (497 - 15,359), large (15,360 - 16,773,120) and huge (16,773,121+) (note that those ranges are for 32-bit systems). For tiny and small allocations malloc maintains its own internal memory pool. So if you malloc 16 bytes 65,536 times the tiny pool will grow to 1mb. This memory will never be reclaimed by the system. However, if you free that memory it will be reused by the same process for future tiny allocations. Large and huge allocations are reclaimed by the system when freed.

This means that if a program makes a large number of small allocations one time, that one time will grow the process' resident memory to it's largest level, which may be significantly larger than the programs regular memory usage. The system will eventually move the unused pages to disk if necessary.

Really I think this behavior may not be optimal for OS X. In a GUI app it is possible for user to do something which will make a large number small allocations one time and then free that memory all at once, bring the app's resident memory to a high level. If enough programs do this then RAM will become filled with freed memory, and the system will start swapping, which may make things sluggish. If freed memory was actually reclaimed by the system you wouldn't see this. OpenBSD's implementation of free() actually does this.</description>
		<content:encoded><![CDATA[	<p>In general, most Unix systems do not return malloced memory to the system when freed (although there are exceptions for large allocations). On OS X allocations take place in one of four categories: tiny (1 &#8211; 496 byes), small (497 &#8211; 15,359), large (15,360 &#8211; 16,773,120) and huge (16,773,121+) (note that those ranges are for 32-bit systems). For tiny and small allocations malloc maintains its own internal memory pool. So if you malloc 16 bytes 65,536 times the tiny pool will grow to 1mb. This memory will never be reclaimed by the system. However, if you free that memory it will be reused by the same process for future tiny allocations. Large and huge allocations are reclaimed by the system when freed.</p>
	<p>This means that if a program makes a large number of small allocations one time, that one time will grow the process&#8217; resident memory to it&#8217;s largest level, which may be significantly larger than the programs regular memory usage. The system will eventually move the unused pages to disk if necessary.</p>
	<p>Really I think this behavior may not be optimal for OS X. In a GUI app it is possible for user to do something which will make a large number small allocations one time and then free that memory all at once, bring the app&#8217;s resident memory to a high level. If enough programs do this then RAM will become filled with freed memory, and the system will start swapping, which may make things sluggish. If freed memory was actually reclaimed by the system you wouldn&#8217;t see this. OpenBSD&#8217;s implementation of free() actually does this.</p>

 ]]></content:encoded>
	</item>
</channel>
</rss>
