<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
<channel>
<title><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></title> 
<link>http://jackxiang.com/index.php</link> 
<description><![CDATA[赢在IT，Playin' with IT,Focus on Killer Application,Marketing Meets Technology.]]></description> 
<language>zh-cn</language> 
<copyright><![CDATA[向东博客 专注WEB应用 构架之美 --- 构架之美，在于尽态极妍 | 应用之美，在于药到病除]]></copyright>
<item>
<link>http://jackxiang.com/post//</link>
<title><![CDATA[ [转]malloc/free 的开销，如何去掉这种开销？忘记free内存泄漏怎么办？]]></title> 
<author>jack &lt;xdy108@126.com&gt;</author>
<category><![CDATA[Unix/LinuxC技术]]></category>
<pubDate>Wed, 03 Dec 2014 16:16:04 +0000</pubDate> 
<guid>http://jackxiang.com/post//</guid> 
<description>
<![CDATA[ 
	背景：C语言里重新分配及释放结构体会产生一些开销，可能导致巨大的性能瓶颈。解决这个问题的一个办法是为分配的结构体单独维护一个表。当用户不需要某个结构体实例时，将其返回结构体池中。当我们需要某个实例时，从结构体池中获取一个对象。如果池中没有可用的元素，我们就可以动态分配一个实例。这种方法高效地维护一个结构体池，能按需重复使用动态内存。<br/>&nbsp;&nbsp;&nbsp;&nbsp; 一般的malloc实现，对一块已分配的内存，都有两个机器字的簿记，甚至更多。如果不需要排错，理论上讲，只需要一个字长的额外开销，用来记录这块内存的尺寸（放在intptr[-1]处是个好主意）。<br/>为什么需要这个开销呢？因为free传入的只是个指针，它不知道要释放多大的内存，因此free内部必须通过某种方式来获得这块内存的尺寸。<br/>可以想象，如果用 malloc/free 来作为一个关联数组（map）的分配器，要浪费不少内存。不过好在实际数据的尺寸往往比额外消耗要大很多，相比起来，浪费的比例不算很大，况且现在内存还很便宜。<br/>其实，打造一个高效的分配器并不难，难的是它的适用范围（多线程？cell尺寸，chunk尺寸，对齐，排错...），如果可以忍受这些缺陷，或者说是限制，还是比较值得的。下一步就是它的灵活性——让它可以更加容易集成进其它系统。<br/>对于C标准库，如果能增加一个/一族这样的分配器，还是很有价值的。从理论上讲，只要free时多传一个size参数，就可以完全去掉额外的开销。这样两个函数就可以做到：<br/><textarea name="code" class="php" rows="15" cols="100">
void* salloc(size_t size);&nbsp;&nbsp;
void&nbsp;&nbsp;sfree(void* ptr, size_t size);&nbsp;&nbsp;
</textarea><br/>这样做还有一个额外的好处，就是可以更好地对齐，假定程序需要按32字节对齐，malloc/free 就至少需要32字节做簿记，如果再加上内存越界检测，就需要64字节。salloc/sfree则只需要将分配的内存对齐到32字节边界即可。<br/> <br/>但是这对程序的正确性要求很高，malloc/free中，内存越界检测可以很容易实现，而salloc/sfree就完全做不到（除非增加额外簿记）。一个好主意是可以在debug版中加入这些差错功能，而在release版中去掉。<br/> <br/>更好（确切地讲应该是更灵活）的方案是，实现一个<br/><textarea name="code" class="php" rows="15" cols="100">
struct mpool&#123;&nbsp;&nbsp;
&nbsp;&nbsp;// .....&nbsp;&nbsp;
&#125;;&nbsp;&nbsp;
&nbsp;&nbsp;
// return success or fail&nbsp;&nbsp;
int mpool_init(struct mpool* pool);&nbsp;&nbsp;
void mpool_destroy(struct mpool* pool);&nbsp;&nbsp;
void* mpalloc(struct mpool* pool, size_t size);&nbsp;&nbsp;
void&nbsp;&nbsp;mpfree(struct mpool* pool, void* ptr, size_t size);&nbsp;&nbsp;
 </textarea><br/><br/>而让 salloc/sfree简单地作为 mpool 的包装。<br/> <br/>gcc的std::allocator基本上是按这样的方式实现的，只不过，它的size参数，大多数时刻是自动传递的（知道具体的class/struct，也就知道它的尺寸）。实现方式上，使用 size_aligned/align 作为索引去访问特定尺寸的mempool，一个 mempool 是多个链表串起来的大chunk，每个chunk内部是链表穿起来的cell。这也许是最好的实现方式了，除了节省的额外空间开销，时间开销上，如果不考虑加锁，一次alloc平均可以在10时钟周期内完成，dealloc用的时间更短。相比之下malloc/free耗的时间也要多得多。<br/>原文来自：http://blog.csdn.net/whinah/article/details/4693828<br/><br/>如何减少频繁分配内存（malloc或者new）造成的内存碎片？<br/>高性能之内存池（频繁使用malloc和new会降低性能）<br/>内存池(Memory Pool)是一种内存分配方式。 通常我们习惯直接使用new、malloc等API申请分配内存，这样做的缺点在于：由于所申请内存块的大小不定，当频繁使用时会造成大量的内存碎片并进而降低性能。内存池则是在真正使用内存之前，先申请分配一定数量的、大小相等(一般情况下)的内存块留作备用。当有新的内存需求时，就从内存池中分出一部分内存块，若内存块不够再继续申请新的内存。这样做的一个显著优点是尽量避免了内存碎片，使得内存分配效率得到提升。<br/><br/>（1）针对特殊情况，例如需要频繁分配释放固定大小的内存对象时，不需要复杂的分配算法和多线程保护。也不需要维护内存空闲表的额外开销，从而获得较高的性能。<br/>（2）由于开辟一定数量的连续内存空间作为内存池块，因而一定程度上提高了程序局部性，提升了程序性能。<br/>（3）比较容易控制页边界对齐和内存字节对齐，没有内存碎片的问题。<br/>（4）当需要分配管理的内存在100M一下的时候，采用内存池会节省大量的时间，否则会耗费更多的时间。<br/>（5）内存池可以防止更多的内存碎片的产生<br/>（6）更方便于管理内存<br/>转自：http://blog.sina.com.cn/s/blog_6abf2c040101fj3f.html<br/><br/><br/>忘记free内存泄漏怎么办？<br/>linux C内存泄露检测实现及内存泄露检测的一般方法<br/>linux中，由于使用malloc或alloc而没有free掉申请的内存，就会造成内存的泄露。通常，来讲为了避免内存泄露的情况出现，一般要求，我们尽量的malloc之后，调用free。但是总会有忘记free的时候啊。一般可以有如下几种方式来避免内存泄露：<br/><br/>1）&nbsp;&nbsp;使用智能指针，这个在C++中较为常见；<br/><br/>2）&nbsp;&nbsp;使用内存池；<br/><br/>3）&nbsp;&nbsp;自己封装一层malloc/free等等。当申请内存时，将申请信息放入到一个已分配内存信息链表里面。free时，删除对应的信息表的节点。在程序执行结束前，扫瞄该信息表，若还存在信息节点，那么该节点记录的就是泄露的内存信息。若链表为空，那就是说没有发生内存泄露；<br/><br/>4）使用检测工具检测内存泄露，进而修补程序，这样的工具有比如Valgrind等等。<br/><br/>摘录自：http://www.xuebuyuan.com/1764051.html
]]>
</description>
</item><item>
<link>http://jackxiang.com/post//#blogcomment</link>
<title><![CDATA[[评论]  [转]malloc/free 的开销，如何去掉这种开销？忘记free内存泄漏怎么办？]]></title> 
<author> &lt;user@domain.com&gt;</author>
<category><![CDATA[评论]]></category>
<pubDate>Thu, 01 Jan 1970 00:00:00 +0000</pubDate> 
<guid>http://jackxiang.com/post//#blogcomment</guid> 
<description>
<![CDATA[ 
	
]]>
</description>
</item>
</channel>
</rss>