디폴트 힙의 비교 (메모리풀 이용) [윈도우 ,리눅스]
#include <malloc.h> #include <boost/progress.hpp> #include <boost/pool/pool.hpp> struct STest { char buffer[4]; }; const int MAX = 1000000; void* pT[MAX]; void New_Delete() { boost::progress_timer t; for(int i=0; i < MAX; ++i) { pT[i] = malloc(sizeof(STest));//new STest; } for(int i=0; i < MAX; ++i) { free(pT[i]); } } boost::pool<> MemPool(sizeof(STest)); void MemoryPool() { boost::progress_timer t; for(int i=0; i < MAX; ++i) { pT[i] = MemPool.malloc(); } for(int i=0; i < MAX; ++i) { MemPool.free( pT[i] ); } } int main(int argc, _TCHAR* argv[]) { New_Delete(); MemoryPool(); return 0; }
윈도우 평균디폴트 힙 0.43 s
메모리풀 0.04 s
리눅스 평균
디폴트힙 0.35 s
메모리풀 0.16 s
#include <malloc.h> #include <boost/progress.hpp> #include <boost/pool/pool.hpp> struct STest { char buffer[4]; }; struct STest2 : public STest { char buffer[4]; }; struct STest3 : public STest2 { char buffer[4]; }; struct STest4 : public STest3 { char buffer[4]; }; struct STest5 : public STest4 { char buffer[4]; }; const int MAX = 200000; void* pT[MAX]; void* pT2[MAX]; void* pT3[MAX]; void* pT4[MAX]; void* pT5[MAX]; void New_Delete() { boost::progress_timer t; for(int i=0; i < MAX; ++i) { pT[i] = malloc(sizeof(STest));//new STest; } for(int i=0; i < MAX; ++i) { pT2[i] = malloc(sizeof(STest2));//new STest; } for(int i=0; i < MAX; ++i) { pT3[i] = malloc(sizeof(STest3));//new STest; } for(int i=0; i < MAX; ++i) { pT4[i] = malloc(sizeof(STest4));//new STest; } for(int i=0; i < MAX; ++i) { pT5[i] = malloc(sizeof(STest5));//new STest; } for(int i=0; i < MAX; ++i) { free(pT[i]); } for(int i=0; i < MAX; ++i) { free(pT2[i]); } for(int i=0; i < MAX; ++i) { free(pT3[i]); } for(int i=0; i < MAX; ++i) { free(pT4[i]); } for(int i=0; i < MAX; ++i) { free(pT5[i]); } } boost::pool<> MemPool(sizeof(STest)); boost::pool<> MemPool2(sizeof(STest2)); boost::pool<> MemPool3(sizeof(STest3)); boost::pool<> MemPool4(sizeof(STest4)); boost::pool<> MemPool5(sizeof(STest5)); void MemoryPool() { boost::progress_timer t; for(int i=0; i < MAX; ++i) { pT[i] = MemPool.malloc(); } for(int i=0; i < MAX; ++i) { pT2[i] = MemPool2.malloc(); } for(int i=0; i < MAX; ++i) { pT3[i] = MemPool3.malloc(); } for(int i=0; i < MAX; ++i) { pT4[i] = MemPool4.malloc(); } for(int i=0; i < MAX; ++i) { pT5[i] = MemPool5.malloc(); } for(int i=0; i < MAX; ++i) { MemPool.free( pT[i] ); } for(int i=0; i < MAX; ++i) { MemPool2.free( pT2[i] ); } for(int i=0; i < MAX; ++i) { MemPool3.free( pT3[i] ); } for(int i=0; i < MAX; ++i) { MemPool4.free( pT4[i] ); } for(int i=0; i < MAX; ++i) { MemPool5.free( pT5[i] ); } } int main(int argc, _TCHAR* argv[]) { New_Delete(); MemoryPool(); return 0; }
윈도우 평균디폴트 힙 0.91 s
메모리풀 0.20 s
리눅스 평균
디폴트 힙 0.75 s
메모리풀 0.53 s
//-----------------------------
위의 코드를 연속해서 4번을 돌려 본 결과
리눅스 평균0.76 s
0.55 s
0.76 s
0.23 s
0.62 s
0.23 s
0.62 s
0.23 s
윈도우 평균0.94 s
0.19 s
1.08 s
0.13 s
1.11 s
0.11 s
1.08 s
0.14 s
컴파일 환경
윈도우XP : VC++7.1
레드헷 8.0 : gcc (GCC) 3.2.2 20030222 (Red Hat Linux 3.2.2-5)
최적화 옵션은 VC++ 경우 릴리즈 모드로 하였고
gcc 는 -O2로 하였다
--- 단 컴퓨터는 윈도우 XP가 깔려있는 컴퓨터는 애슬론 XP 1600+ 였으며
레드헷이 깔려있는 컴퓨터는 1기가 CPU 2개가 달린 서버 컴퓨터 --------------
MAX 값을 변경하여 측정해보았으나 선형적으로 변함 , MAX값에 따른 차이는 없음
추론 : 윈도우는 힙을 관리함에 있어서 리눅스와 많이 다른 구조를 보인다 예를 들면 디폴트 힙을 선형 메모리로 발급 받고 그것을 관리하기때문에, 상당히 부하가 심한듯 보이고 따라서 메모리풀을 사용했을시에는 대단히 큰 효과를 볼수 있었다 그리고 메모리풀 종류를 늘려 테스트 한 결과로는 그 격차가 좁혀 졌으나 , 아무래도 메모리풀을 하나로 쓸때보단 여러개로 쓸때 메모리풀의 재 할당횟수가 증거 되어 이런 결과를 보인것으로 추정된다 재할당 이내 폭이었다면 결과는 비슷하지 않았을까로 추정함
그리고 나중에 연속해서
연속 4번 돌려 그 메모리풀을 다시 사용했을 경우
리눅스의 경우
리눅스 디폴트 힙보다 3배가 빨라졌다
그리고 리눅스 디폴트힙 자체도 조금 빨라지긴 했다
결국 재할당을 고려하지 않는 다면 메모리풀이 디폴트 힙보다 3배 빠른셈
윈도우는 디폴트 힙이 오히려 나중에 더 느려지는 결과를 보였다
메모리풀은 현저한 성능이 증가하진 않았지만 맨 처음보다 나중에 20-30%
빨라진것을 봐선 메모리풀의 재할당 문제때문인거 같아 보인다
사실 리눅스에서 돌아가는 컴퓨터와 종류가 다르기때문에 정확한 테스트라고 100% 장담하긴 힘드나
리눅스에서 돌아가는 boost 메모리풀 코드가 , 윈도우쪽 boost 메모리풀과 거의 똑같기 때문에 리눅스의 힙 관리가 윈도우보다 훨씬 빠른걸로 보인다
자세한 힙 관리 구조를 알고 싶은분은
리눅스 -> 유닉스의 내부 라는 책을 참고하고
윈도우 -> 제프리 리처의 책을 참고하기 바랍니다
ps 편의상 반말로 -_-; 하였습니다 참 실수한게 있어서
코드를 바꿨습니다
상속을 잘못 시켰습니다
또한 결과 값이 바뀌었습니다
좀 되긴 했지만 저도 비슷한 놈을 만들어서 그래프를 그려본 적이 있었는데
좀 되긴 했지만 저도 비슷한 놈을 만들어서 그래프를 그려본 적이 있었는데, 솔라리스(Sparc)에서의 결과가 굉장히 인상적이었던 것이 기억에 남는군요. 리눅스는 2.4 부근의 버전이었으니 요즘은 어떻게 될지는 잘 모르겠지만...
평균치보다는 할당하는 object의 수, 할당하는 object의 크기와 allocation 시간을 비교해보신다면 좀 더 재미있는 결과를 찾으실지도 모르겠습니다.
리눅스 커널 버젼도 명시해주어야 하지 않을까요?2.4와 2.6이 같은
리눅스 커널 버젼도 명시해주어야 하지 않을까요?
2.4와 2.6이 같은것 같지는 않은데요...
----
먼저 알게 된 것을 알려주는 것은 즐거운 일이다!
http://hangulee.springnote.com
http://hangulee.egloos.com