首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件架构设计 >

软件架构设计之Utility模块——内存储器分配

2013-03-19 
软件架构设计之Utility模块——内存分配一:前言内存分配当然是对动态内存的分配(动态内存是在堆中分配的),使

软件架构设计之Utility模块——内存分配
一:前言

内存分配当然是对动态内存的分配(动态内存是在堆中分配的),使用动态内存的优点:

1.动态内存可以在不同的对象与函数之间共享。

2.动态分配的内存空间的大小可以在运行时确定。

关于内存的知识不想过多的解释,毕竟这是一篇注重设计与实现的文章,让我们把重点转移到:我们为什么要内存分配器,如何实现,对于多种实现,我们该如何抉择,实现后的效果如何等等一系列问题。

二:为什么要内存分配器

会有很多人说,内置的内存分配功能就已经足够使用了,还需要自己去分配内存吗?自己分配内存一般是指:先分配一大块(Chunk)内存,并在需要时将此内存按片(Block)进行分发。以下说说下内存分配器的好处:

1:可能会减少资源的开销,使用new分配内存时,系统还需额外的空间(4~32个bytes)来记录所分配的内存,在调用Delete释放的时候就可以依此来释放已分配的内存,这个额外的空间对于大对象来说所占比例太小,显得微不足道,而对于小对象就有点不可接受了。而即使是大对象而程序中大量的这种对象,额外的空间开销也是不容忽视的。使用内存分配器可以一次分配一大块内存可大大减少该额外空间。

2:这样我们可以申请连续的内存,提高Cache的命中率。

我们关注的重点是小对象的分配,大对象由于系统额外影响所占的比例有限因此不是我们考量的重点,但它仍然可以优化,所以这里均实作了出来。

三:内存分配器实现

这里我将设计两种内存分配(大对象内存分配,小对象内存分配),大对象与小对象如何区分呢?我就把它们以64bytes作为分界线,详细内容可参看《Modern C++ Design》的“小型对象分配技术”章节。这里的内存分配方式即采用该书中的小对象分配原理,并作了适当修改以适应大对象的分配及本软件设计。对于大对象分配又可划分两种:占住式(Hold),即分配了即不会归还给系统,Delete时将地址添加到空闲链表中,弹性式(Flex),即当大块均空闲时将该大块归还给系统。

先来说说公共部分吧。上面说了,公共部分就是大块内存(里面还有n个大小一样的区块),及管理这些大块内存的类叫FixedAllocator,大块内存叫Chunk,区块叫Block,下面就直接叫其英文名了。

1.    HTMemChunk实现

先看类定义:

HTSmallAllocator::HTSmallAllocator( std::size_t numBlocks, std::size_t maxBlockSize ): m_pLastAlloc(0), m_pLastDealloc(0), m_numBlocks(numBlocks), m_maxBlockSize(maxBlockSize){}void* HTSmallAllocator::Allocate( std::size_t numBytes ){if (numBytes > m_maxBlockSize) return operator new(numBytes);if (m_pLastAlloc && m_pLastAlloc->BlockSize() == numBytes){return m_pLastAlloc->AllocateImpl(numBytes);}HTFixedAllocator fixAlloc;fixAlloc.Init(numBytes, m_numBlocks);Pool::iterator i = std::lower_bound(m_pool.begin(), m_pool.end(), fixAlloc, CompareFixedAllocatorSize());if (i == m_pool.end() || i->BlockSize() != numBytes){i = m_pool.insert(i, fixAlloc);m_pLastDealloc = &*m_pool.begin();}m_pLastAlloc = &*i;return m_pLastAlloc->AllocateImpl(numBytes);}void HTSmallAllocator::Deallocate( void* p, std::size_t numBytes ){if (numBytes > m_maxBlockSize) return operator delete(p);if (m_pLastDealloc && m_pLastDealloc->BlockSize() == numBytes){m_pLastDealloc->DeallocateImpl(p);return;}HTFixedAllocator fixAlloc;fixAlloc.Init(numBytes, m_numBlocks);Pool::iterator i = std::lower_bound(m_pool.begin(), m_pool.end(), fixAlloc, CompareFixedAllocatorSize());assert(i != m_pool.end());assert(i->BlockSize() == numBytes);m_pLastDealloc = &*i;m_pLastDealloc->DeallocateImpl(p);}

这里的问题是找到相应blockSize的HTFixedAllocator,这里采用和HTFixedAllocator相同的策略,为了提高查找速度,我们将m_pool按blockSize大小排序。

HTMemSmall重载了系统提供的operatornew和operator delete。这样生成一个HTMemSmall派生对象就可以使用其好处。

四:测试结果大家可以使用以上的代码进行测试,望大家将测试结果告知与我。我希望我们可以一起探讨一起互动……

热点排行