pjlib的内存池可以像c++的new操作符和c的malloc函数一样动态地分配内存,new操作符和c的malloc存在性能瓶颈和分段问题,因而不是为高性能应用和实时应用程序设计的。相对于传统的new和malloc以及一般的内存池实现,pjlib的内存池好处更多,这是因为它:
--允许分配不同大小的内存块,这一点与别的内存池实现不同。
--快速简单,O(1)时间复杂度,只有少量的指针算法,且不要求任何互斥加锁。
--高效,池不需要跟踪每个分配的内存块,因而每次分配内存块都没有额外的负担,但可能要浪费少量(最多PJ_POOL_ALIGNMENT-1)的字节内存用于字节对齐。
--防止内存泄漏,有垃圾收集功能。事实上并不需要释放从池分配的内存,当池销毁时,之前分配的所有块都会全部释放。
pjlib内存池还为应用程序提供了其他的一些可用性和可伸缩性:
--可以跟踪内存泄漏,每个池都赋有名称,应用程序可以检查到哪个内存池没有释放;
--从池中分配内存并不设计成线程安全的,我们假设一个更高层的对象会拥有一个池,它会管理池的线程安全性,这样可以得到更快的池操作并防止不需要的锁操作;
--缺省行为,如c++的new一样,在内存分配失败时,会抛出一个PJ_NO_MEMORY_EXCEPTION异常,这样可以在上层处理异常而不是每次检查pj_pool_alloc函数调用的返回值。如果应用程序不喜欢这么做,可以通过给池工厂提供不同的池策略来从全局上改变缺省行为。
--可以使用任意的后端分配器(allocator)和析构器(deallocator)来分配内存,缺省的策略是使用malloc()和free()函数,但应用程序可以使用不同的策略,比如可以从一个全局静态的内存区域分配内存块。
使用pjlib内存池的一些注意事项:
--在创建内存池的时候,pjlib要求应用程序指定初始大小,一旦池创建完成,pjlib从系统分配初始大小的内存。应用程序的设计者必须慎重地选择初始大小,因为太大会导致系统内存的浪费。而且池是可以增长的,应用程序的设计者可以在创建池的时候,指定按照什么尺寸来增长池大小。
--无论如何,池是不能缩小的!因为没有函数deallocate内存块,所以内存池也没有办法把不使用的内存释放归还系统。应用程序设计者必须清楚,如果从生命期无限的内存池中持续不断地分配内存,会导致应用程序的内存占用随时间而不断增长。