일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 루아
- 비교 함수 객체
- lua
- 예외
- 게임
- Effective c++
- 반복자
- more effective c++
- effective stl
- resource management class
- exception
- 스마트 포인터
- 영화
- reference
- 참조자
- 언리얼
- 메타테이블
- 암시적 변환
- 오블완
- 티스토리챌린지
- implicit conversion
- virtual function
- 영화 리뷰
- operator new
- 상속
- UE4
- Smart Pointer
- 함수 객체
- c++
- 다형성
Archives
- Today
- Total
스토리텔링 개발자
[Effective STL] 11. 커스텀 할당자(Custom Allocator) 본문
728x90
항목 11. 커스텀 할당자를 제대로 사용하는 방법을 이해하자
커스텀 할당자를 쓰고 싶어지는 경우
- 벤치마킹, 프로파일링, 각종 실험을 통해 디폴트 STL 메모리 관리자(allocator<T>)가 별로라는 결론에 이르렀을 때
- 낮은 메모리 효율, 심각한 단편화(fragmentation) 등
- allocator<T>가 쓰레드 안전성을 염두에 둔 것이 마음에 들지 않을 때
- 단일 쓰레드 환경에서만 사용할텐데, 동기화 때문에 걸리는 필요 없는 오버헤드를 피하고 싶다.
- 컨테이너에 들어 있는 객체들이 하나의 힙 안에서 관리되는 점 때문에 문제를 느낄 때
- 같은 종류의 객체를 특정한 힙에 모여있게 하여 메모리 참조 위치의 근접성(locality of reference)를 극대화하는 효과를 얻기 부족하다.
- 공유 메모리에 해당하는 특수한 힙을 만들어, 하나 이상의 컨테이너를 그 메모리에 두어 여러 프로세스들이 공유할 수 있게 하고 싶을 때
커스텀 할당자 구현 예시
- 공유 메모리를 할당하는 커스텀 함수들을 사용하여 커스텀 할당자를 구현하는 방법
// malloc, free를 본뜬 함수
void* mallocShared(size_t bytesNeeded);
void freeShared(void* ptr);
// 커스텀 할당자 구현
template<typename T>
class SharedMemoryAllocator
{
public:
...
// 항목 10 참조
pointer allocate(size_type numObjects, const void* localityHint = 0)
{
return static_cast<pointer>(mallocShared(numObjects * sizeof(T)));
}
void deallocate(pointer ptrToMemory, size_type numObjects)
{
freeShared(ptrToMemory);
}
...
};
typedef vector< double, SharedMemoryAllocator<double> > SharedDoubleVec;
...
{
SharedDoubleVec v; // 요소들이 공유 메모리에 있게 되는 벡터
// 허나, 벡터 v 및 내부의 데이터 멤버는 공유 메모리에 있지 않다.(스택에 있다.)
...
} // v 해제
- 위 예제에서, 벡터의 요소는 공유 메모리에 있지만, 벡터 자체는 스택에 있다.
- 벡터 자체를 공유 메모리에 두는 방법
// SharedDoubleVec 객체를 담을 충분한 공유 메모리 할당(allocate)
// mallocShared가 nullptr을 리턴하는 경우는 고려하지 않았다.
void* pVectorMemory = mallocShared(sizeof(SharedDoubleVec));
// '위치지정 new(placement new)'를 써서 SharedDoubleVec 객체를 메모리에 생성
SharedDoubleVec* pv = new (pVectorMemory) SharedDoubleVec;
... // 벡터 객체를 사용한다.
pv->~SharedDoubleVec(); // 공유 메모리의 이 객체를 소멸시킨다.
freeShared(pVectorMemory); // 공유 메모리의 메모리 단위를 해제(deallocator)한다.
- 두 개의 힙 클래스에서 메모리를 관리하는 방법
class Heap1
{
public:
...
static void* alloc(size_t numBytes, const void* memoryBlockToBeNear);
static void dealloc(void* ptr);
...
};
class Heap2
{
public:
...
static void* alloc(size_t numBytes, const void* memoryBlockToBeNear);
static void dealloc(void* ptr);
...
};
// STL 컨테이너 몇 개를 종류에 맞춰 제각기 다른 힙에 모아두고 싶다.
// Heap1, Heap2의 인터페이스를 사용하는 커스텀 할당자 템플릿 클래스를 만든다.
template<typename T, typename Heap>
SpecificHeapAllocator
{
public:
...
pointer allocate(size_t numObjects, const void* localityHint = 0)
{
return static_cast<pointer>(Heap::alloc(numObjects * sizeof(T), localityHint));
}
void deallocate(pointer ptrToMemory, size_type numObjects)
{
Heap::dealloc(ptrToMemory);
}
...
};
// 벡터와 셋은 Heap1에 모은다.
vector< int, SpecificHeapAllocator<int, Heap1> > v;
set< int, SpecificHeapAllocator<int, Heap1> > s;
// 리스트와 맵은 Heap2에 모은다.
list< Widget, SpecificHeapAllocator<Widget, Heap2> > l;
map< int, string, less<int>, SpecificHeapAllocator< pair<const int, string, Heap2> > > m;
- 위에서 SpecificHeapAllocator는 객체가 아니라 타입으로 사용된다.
- STL에서는 같은 타입의 다른 할당자 '객체'를 사용하여 다른 STL 컨테이너를 초기화할 수 있지만, 하지 말자.
- Heap1과 Heap2가 타입이 아니라 객체(object)라면 이 둘은 동등한 할당자가 아니고,
- 그러므로 할당자의 등등성(equivalence) 제약을 어기게 되기 대문이다.(항목 10 참조)
- 할당자의 동등성 제약만 잘 지키면 커스텀 할당자 사용에는 문제가 없을 것이다.
728x90
'개발 > Effective STL' 카테고리의 다른 글
[Effective STL] 13. 배열보다 vector (0) | 2024.11.20 |
---|---|
[Effective STL] 12. 쓰레드 안전성 (0) | 2024.11.19 |
[Effective STL] 10. 할당자(Allocator)의 제약 사항 (1) | 2024.11.14 |
[Effective STL] 9. 컨테이너별 요소 삭제 (0) | 2024.11.13 |
[Effective STL] 8. auto_ptr 금지 (0) | 2024.11.12 |
Comments