在VS2012中测试如下代码:
#include <ctime> #include <iostream> using namespace std; class Complex { public: Complex(double a, double b) : r(a),c(b) { } private: double r; //实部 double c; //虚部 }; int main(int argc, _TCHAR* argv[]) { Complex* array[1000]; clock_t t1,t2; t1 = clock(); for (int i = 0; i < 5000; i++) { for (int j = 0; j < 1000; j++) { array[j] = new Complex(i,j); } for (int j=0;j<1000;j++) { delete array[j]; } } t2 = clock(); cout << t2-t1 << "ms" << endl; return 0; }考虑到VS2010中Debug版本和Release版本运行效率的差异,分别使用Debug模式和Release模式编译运行程序,得到结果:
debug模式下:
Release模式下:
Release模式下,程序的运行效率是要远远高于debug模式的,这是因为debug模式中有很多调试信息,而且没有对程序进行优化。
STL中vector容器,在当前容器空间不足时,总是以两倍的方式去分配空间。其主要的问题也是在于使用new操作符或者malloc函数向系统申请内存这一过程是比较耗时。照此看可以采取先多分配一些空间,这样就可以减少使用new和malloc的次数,相应的客户代码与系统内核间的切换次数就大大减少了。根据IBM的一篇文章(简单的内存池办法,文章在博客结尾提供下载地址),按照其思路来优化我们上述的代码。
流程如下:
1、考虑在程序开始运行的时候就去申请一段内存空间,我们定义一个全局的对象,通过这个对象的构造函数来完成初始内存的申请工作。
假设该全局对象定义如下:
MemoryManager gMemoryManager;
2、对我们已经写好的类进行new,new[],delete,delete[]的重载,是我们在调用这些操作符的时候转而去调用上一步中全局对象,让该全局对象给我们提供空间。这样,改写上述的Complex类:
class Complex { public: Complex (double a, double b): r (a), c (b) {} //重载new操作符 inline void* operator new(size_t size) { return gMemoryManager.allocate(size); } //重载delete操作符 inline void operator delete(void* object) { gMemoryManager.free(object); } //重载new[]操作符 inline void* operator new [](size_t size) { return gMemoryManager.allocate(size); } //重载delete[]操作符 inline void operator delete [](void* object) { gMemoryManager.free(object); } private: double r; // Real Part double c; // Complex Part };
//设计该接口在此案例中并没有突出的作用 class IMemoryManager { public: virtual void* allocate(size_t) = 0; virtual void free(void*) = 0; }; class MemoryManager : public IMemoryManager { private: struct FreeStore { FreeStore *next; }; void ExpandPoolSize(); //扩展内存空间 void CleanUp(); //清理内存 FreeStore* freestorehead; public: MemoryManager() { freestorehead = NULL; ExpandPoolSize(); } ~MemoryManager() { CleanUp(); } void* allocate(size_t); void free(void*); }; //程序启动时,内存池默认的空间大小 const int POOLSIZE = 128; //提供给外部访问 void* MemoryManager::allocate(size_t size) { if (0 == freestorehead) ExpandPoolSize(); FreeStore *head = freestorehead; freestorehead = head->next; return head; } //提供给外部访问 void MemoryManager::free(void* object) { FreeStore* head = static_cast<FreeStore*>(object); head->next = freestorehead; freestorehead = head; } //内部访问,扩充内存 void MemoryManager::ExpandPoolSize() { size_t size = (sizeof(Complex) > sizeof(FreeStore*)) ? sizeof(Complex) : sizeof(FreeStore*); FreeStore* head = reinterpret_cast<FreeStore*>(new char[size]); freestorehead = head; for (int i = 0; i < POOLSIZE; i++) { head->next = reinterpret_cast<FreeStore*>(new char[size]); head = head->next; } head->next = 0; } //清理内存 void MemoryManager::CleanUp() { FreeStore* nextPtr = freestorehead; for (; nextPtr; nextPtr = freestorehead) { nextPtr = freestorehead; freestorehead = freestorehead->next; delete []nextPtr; } }
上述过程的完整代码如下:
memoty.h
#ifndef __MEMORY_H__ #define __MEMORY_H__ class IMemoryManager { public: virtual void* allocate(size_t) = 0; virtual void free(void*) = 0; }; class MemoryManager : public IMemoryManager { struct FreeStore { FreeStore *next; }; void ExpandPoolSize(); //扩展内存空间 void CleanUp(); //清理内存 FreeStore* freestorehead; public: MemoryManager() { freestorehead = NULL; ExpandPoolSize(); } ~MemoryManager() { CleanUp(); } void* allocate(size_t); void free(void*); }; #endif //
#include <iostream> using namespace std; #include "memory.h" #include "comlpex.h" //全局的内存管理对象 MemoryManager gMemoryManager; //程序启动时,内存池默认的空间大小 const int POOLSIZE = 128; //提供给外部访问 void* MemoryManager::allocate(size_t size) { if (0 == freestorehead) ExpandPoolSize(); FreeStore *head = freestorehead; freestorehead = head->next; return head; } //提供给外部访问 void MemoryManager::free(void* object) { FreeStore* head = static_cast<FreeStore*>(object); head->next = freestorehead; freestorehead = head; } //内部访问,扩充内存 void MemoryManager::ExpandPoolSize() { size_t size = (sizeof(Complex) > sizeof(FreeStore*)) ? sizeof(Complex) : sizeof(FreeStore*); FreeStore* head = reinterpret_cast<FreeStore*>(new char[size]); freestorehead = head; for (int i = 0; i < POOLSIZE; i++) { head->next = reinterpret_cast<FreeStore*>(new char[size]); head = head->next; } head->next = 0; } //清理内存 void MemoryManager::CleanUp() { FreeStore* nextPtr = freestorehead; for (; nextPtr; nextPtr = freestorehead) { nextPtr = freestorehead; freestorehead = freestorehead->next; delete []nextPtr; } }
#include <iostream> #include <string> using namespace std; #include "memory.h" #include "comlpex.h" #include <ctime> int main() { Complex* array[1000]; clock_t t1, t2; t1 = clock(); for (int i = 0;i < 5000; i++) { for (int j = 0; j < 1000; j++) { array[j] = new Complex (i, j); } for (int j = 0; j < 1000; j++) { delete array[j]; } } t2 = clock(); cout<<t2-t1<<"ms"<<endl; return 0; }
文章下载