프로그램이 런타임 중에 동적으로 메모리를 할당하려면 new/delete
키워드를 사용하여 운영체제한테 메모리를 요구합니다.
이 때 시스템 콜을 시작으로(커널 모드 진입) 전역 힙에서 요청한 크기의 블록을 찾고 Free list 를 관리하며 필요한 경우 메모리 페이지 테이블 업데이트 등의 작업을 수행하고 여러 스레드가 동시에 힙에 접근하는 것을 막기 위해 동기화 작업도 진행됩니다.
현대의 응용 프로그래밍은 이런 내부적인 상황까지 고려하여 설계하지 않겠지만, 최적화 관점에서 볼 때 동적으로 생성하는 것(메모리, 스레드 등등)을 최소화하면 좋다는 것입니다! 😄
🔍 메모리풀
💡 Quotation
메모리 풀(memory pool)은 고정된 크기의 블록을 할당하여
malloc
이나 C++ 의new
연산자와 유사한 메모리 동적 할당을 가능하게 해준다.malloc
이나new
연산자 같은 기능들은 다양한 블록사이즈 때문에 단편화를 유발시키고, 파편화된 메모리들은 퍼포먼스 때문에 실시간 시스템에서 사용할 수 없게 된다. - Wikipeida
우선 thread-unsafety 한 단순한 메모리풀을 만들어 보겠습니다. 여러 데이터 타입에 대응될 수 있게 템플릿으로 만들어야 할 것이며 동적으로 만드는 것이 아니라 배열을 이용해도 될 것 같습니다. 😎
|
|
✅ 5: 템플릿에 쓰이는 것들은 모두 컴파일 타임 때 고정됨 (
capacity
는 배열을 생성할 때 배열의 사이즈로 들어갈 수 있음)
✅ 7: Linked list 를 사용하기 위한 구조체 정의💡 메모리풀 관리 관련
- 데이터 블록
_chunk
를 미리 할당 받음- ✨ allocate 전 까지는 사용하지 않는 빈 메모리를
Linked list
로 이용reinterpret_cast
로LinkedList
형과T
형을 자유롭게 변형할 수 있음✅ 10, 11: 메모리 정렬과 블록 크기를 정하는데 최악의 경우를 선택하여 사용함 (최적화)
✅ 23, 32:new/delete
에 대응하는 메서드
✅ 39, 42: 만약 객체일 경우 초기화와 소멸을 담당함
⚖️ new/delete
vs memory pool
- 1 스레드
- 100,000,000 회
시도 | new/delete | memory pool | 차이 | % |
---|---|---|---|---|
1 | 2559 ms | 57 ms | -2502 ms | -97.77 % |
2 | 2620 ms | 60 ms | -2560 ms | -97.70 % |
3 | 2542 ms | 62 ms | -2480 ms | -97.56 % |
4 | 2555 ms | 52 ms | -2503 ms | -97.96 % |
5 | 2522 ms | 55 ms | -2467 ms | -97.81 % |
✅ 정리
- 동적 할당은 생각보다 많은 자원이 들어간다.
- 메모리풀은 미리 Chunk를 할당을 받아 필요한 시점에 O(1) 의 시간으로 할당해 준다.
new/delete
를 많이 사용한다면 메모리풀로 바꿔서 사용하자! 👍- ❌ 위 코드는 thread-unsafety 하므로 멀티 스레드 환경에서는 사용하면 큰일 난다. 😱