메모리 풀을 적용할때 어떤 방법으로 테스트를 해야할까요?
글쓴이: superkkt / 작성시간: 월, 2006/11/06 - 3:15오후
안녕하세요.
지금 개발중인 프로그램이 네트웍으로 데이터 전송시 패킷마다 동적 메모리 할당을 받는 구조로 되어있습니다. 그래서 파일 전송 속도가 잘 안나오고 있습니다. 일단 속도가 느려지는 원인이 빈번하게 발생하는 동적 메모리 할당이라고 판단이 되어서 메모리 풀을 적용해 보려고 합니다.
구글에서 검색해서 그 중에 아래 라이브러리가 간단하게 적용 할 수 있을것 같아서 테스트를 해봤습니다.
어떻게 테스트를 해야할지 몰라서 8KB의 메모리를 할당하고 memset으로 초기화하고 free하는 루틴을 10만번 반복시켜 봤습니다. 그리고 똑같은 루틴으로 일반 malloc / free 함수를 사용해서 테스트 해보구요. 근데 mpool 라이브러리를 사용한 쪽이 4배이상 느리군요. 아무래도 저의 테스트 방법이 뭔가 잘못된것 같은데 어디가 문제인지 모르겠습니다.
이런 단순 비교는 쓸모없는 테스트인가요? 그리고 혹시 위 라이브러리 말고 간단하게 적용해서 사용 할 수 있는 메모리 풀 라이브러리가 있다면 추천 부탁드립니다.
-PS-
개발환경: 리눅스 / C
Forums:
IBM 기술문서중에
IBM 기술문서중에 메모리풀에 대한 내용이 있었는데 시스템 내부적으로 메모리 풀을 구현해놓은 경우에는 오히려 속도가 늦어질 수 있다고 했던 것 같습니다. Sahni 자료구조 책에 보면 매우 간단한 메모리 풀이 나오는데 그것을 한번 써보시죠.
단일 CPU환경에서
단일 CPU환경에서 소량의 데이터 크기를 소수의 쓰레드로 할당/해제하는 것은
큰 차이가 없을 것입니다.
메모리 풀을 쓰는 가장 큰 이유는 루프내부에서 malloc() 관련 함수의 호출로 인해
sbrk()와 같은 실제 시스템 호출을 발생하는 것을 줄이는 것이고,
다중 쓰레드에 의한 contention을 줄이는 것이 두번째 이유입니다.
만일 위에서 만드신 풀의 제대로된 테스트를 원하시면,
메모리 할당 해제의 단위와 총합이 몇십메가를 초과하고, 다수의(수십)개의 쓰레드가
동시에 반복하는 것을 구현해 보시면 성능을 측정하실 수 있을 것입니다.
사족을 붙이자면,
시스템 콜을 줄이기 위해서 미리 메모리를 할당하는 것이구요,
쓰레드 간의 충돌을 줄이기 위해서 메모리 할당 리스트를 CPU*2 정도로 유지하는 것이
대부분의 라이브러리 구현 원리입니다.
AIX 에서는 환경변수로 이러한 동작을 조절할 수 있도록 해 주더군요.
저희 회사내부에서도 3종류의 메모리 풀을 자체적으로 구현해서 사용하고 있습니다.
건승하시길.
고도의 추상화, 극도의 구체화, 에디슨을 그리워하다.
고도의 추상화, 극도의 구체화, 에디슨을 그리워하다.
솔라리스 8과 10의
솔라리스 8과 10의 기본 malloc의 성능과 직접 만든 메모리풀, ace 라이브러리의 메모리풀 몇가지의 성능테스트를 했던적이 있습니다.
malloc는 시스템 콜이기 때문에 오티마이징 옵션으로 컴파일 됐다고 보시면 됩니다.
그래서 디버깅모드로 컴파일한 메모리풀보다 빠르거나 비슷하거나 하더군요.
하지만 직접 구현한 메모리풀을 옵티마이징으로 컴팔하면 malloc 보다 빠릅니다.(제 경우 5배)
멀티쓰레드에서도 사용가능한 메모리풀이라도 malloc 보다는 빠르더군요.(제 경우 2배)
그리고 memset은 메모리 할당/제거와는 관련이 없기 때문에 테스트 코드에서 빼셔야 합니다.
할당 사이즈가 크면, memset이 대부분의 시간을 차지하게 될겁니다.
---------------------------------------------------------------------------------
메모리 풀을 떠나서 네트워킹을 많이 사용하는 프로그램의 성능을 향상시킬려면 복사를 최대한 줄여야 합니다.
메모리 할당 보다 데이터의 복사가 더 큰 문제입니다.
버클리소켓 api 의 문제점 중 하나가 데이터를 송수신하기 위해선 유져에서 커널로, 커널에서 유저로 꼭 데이터 복사가 발생해야한다는 것이지요.
이런 이유로 라우터의 경우는 커널스페이스와 유져스페이스의 개념없이 모두 하나의 메모리 스페이스에서 작동하고 데이터는 모두 복사 없이 포인터로 처리를 한다고 들었습니다.
아~~ 감솨!!!
요즘 메모리 풀에 대한 관심이 많았는뎅...
감솨~~^^
#define DEBUG printf( "%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__ );
#define DEBUG printf( "%s, %s, %d\n", __FILE__, __FUNCTION__, __LINE__ );
프로그램에서
프로그램에서 빈번하게 할당하는 메모리의 사이즈가 아주 작습니다. 단순히 한번에 네트웍으로 전송할 패킷을 저장하는 용도이기 때문에 몇KB ~ 몇십KB 정도입니다. 이렇게 작은 메모리를 빈번하게 할당/해제하는 경우에도 메모리 풀이 효과가 있을까요?
속도가 떨어지는것이 메모리 할당 부분이 아닌것 같다는 생각이.. ^^
======================
BLOG : http://superkkt.com
======================
BLOG : http://superkkt.com
당연히 효과가
당연히 효과가 있습니다.
빈번하게 할당 해제하는 루틴을 malloc(), free()를 사용하면
위 함수의 원래 목적에 맞는 복잡한 루틴을 타게 됩니다.
할당시 최적의 크기를 찾아야 하고, 부족하면 시스템 호출도 해야하고,
해제시에는 해제할 때 연속된 공간이 이미 존재하는지 검사하여 그렇다면,
연속된 메모리의 chunk로 만들어야 하고, 해당 포인터가 잘못되었는지
경우에 따라 검사도 하고......
직접 만드시는 것이 효과가 나을 것이라고 생각합니다.
몇KB에서 몇십KB는 결코 작은 크기가 아닌데요....^^
건승하시길.
고도의 추상화, 극도의 구체화, 에디슨을 그리워하다.
고도의 추상화, 극도의 구체화, 에디슨을 그리워하다.
밑으로 패스
밑으로 패스
Dig it.
성능과 관련해서는
성능과 관련해서는 userspace 와 kernel space 사이의 memcopy 오버해드는 고려해보셨는지
이경우 실제 시스템의 사용가능한 physical 메모리의 양이 벤치마킹에 영향을 줄거라는 생각이 듭니다.
메모리 풀은 maximum data size 가 정해져 있다면 CSLL 또는 CDLL 형식의 free-list 를 사용해보시는것도 괜찮을듯 싶습니다.
Dig it.
동적 메모리를 할당하는 것
union 으로 잡아서 한꺼번에 할당하는건 어떤지
동적메모리 할당...
당연히 빈번한 할당은 피해야합니다 ㅡ.ㅡ;;; (자바나 기타 스크립트 언어라면 어쩔수없지만...)
malloc, new 같은 호출 한번에 인스트럭션이 대충 500개정도;; 호출된다고 들었습니다.
뭐 줏어들은거라서...신빙성은 없습니다만, 일단 동적할당 받으려면 힙영역에 어느곳이 비어있는지 확인하고,
원하는 크기만큼 인지 테스팅 해봐야됩니다. 그리고 해제할때도 마찬가지이구요...게다가 빈번하게 일어나면
Memory Fragment가 점점 일어나겠죠. 그러다보면 할당이 한번에 되질않고 (빈공간 확인하다가 '어? 모자라네'
하면서 재할당하고...) 더 시간이 오래걸릴수 있습니다.
더구나..시스템콜의 경우는 커널과 유저 스페이스를 왔다갔다해서 더욱 느려집니다 -_-;
여튼 결론은 이래저래 느려지기만하니 메모리풀을 쓰세요~ 입니다 ^^;;
------------------------------------------
Let`s Smart Move!!
http://kalstein.tistory.com/
댓글 달기