频繁的分配和回收内存会严重的降低程序的性能。性能降低的原因在于默认的内存管理器是通用的,应用程序会以特定的方式使用内存,并且为不需要的功能付出代价,比方说单线程运行的程序不需要为处理多线程的部分付出代价。设计专用的内存管理器可以解决这个问题,设计时应该至少想到以下两个方面:

  • 大小
  • 并发

从大小角度:

  • 固定大小:分配固定大小内存块的内存管理器
  • 可变大小:分配任意大小内存块的内存管理器。所请求分配的大小实现是未知的。

从并发的角度:

  • 单线程:内存的管理局限在一个线程内。内存被一个线程使用,并且不越出该线程的界限。这种内存管理器不涉及相互访问的多线程。
  • 多线程:内存管理器被多个线程并发地使用。这种实现需要包含互斥执行的代码段。无论什么时候,只能有一个线程在执行一个代码段。

专用Rational内存管理器

  1. class NextOnFreeList {
  2. public:
  3. NextOnFreelist *next;
  4. }
  5. class Rational {
  6. public:
  7. Rational (int a = 0, int b = 1) : n(a), d(b) {}
  8. inline void *operator new(size_t size);
  9. inline void operator delete(void *doomed, size_t size);
  10. static void newMemPool() {expandTheFreeList();}
  11. static void deleteMemPool();
  12. private:
  13. static NextonFreeList *freeList; //Rational对象的空闲列表
  14. static void expandTheFreeList();
  15. enum {EXPANSION_SIZE = 32};
  16. int n;
  17. int d;
  18. }
  19. inline
  20. void* Rational::operator new(size_t size)
  21. {
  22. if (0 == freeList) { //如果列表为空,则将其填满
  23. expandTheFreeList();
  24. }
  25. NextOnFreeList *head = freeList;
  26. freeList = head->next;
  27. return head;
  28. }
  29. //Rational
  30. inline
  31. void Rational::operator delete(void *doomed, size_t size)
  32. {
  33. NextOnFreeList *head = static_cast<NextOnFreeList *>doomed;
  34. head->next = freeList;
  35. freeList = head;
  36. }
  37. void Rational::expandTheFreeList()
  38. {
  39. size_t size = (sizeof(Rational) > sizeof(NextOnFreeList *)) ?
  40. sizeof(Rational) : sizeof(NextOnFreeList *);
  41. NextOnFreeList *runner = static_cast<NextOnFreelist *> new char[size];
  42. freeList = runner;
  43. for(int i = 0; i < EXPANSION_SIZE; i++) {
  44. runner->next =
  45. static_cast<NextOnFreeList *> new char [size];
  46. runner = runner->next;
  47. }
  48. runner->next = 0;
  49. }
  50. void Rational::deleteMemPool()
  51. {
  52. NextOnFreeList *nextPtr;
  53. for (nextPtr = freeList; nextPtr != NULL; nextPtr = freeList) {
  54. freeList = freeList->next;
  55. delete []nextPtr;
  56. }
  57. }

固定大小对象的内存池