3. 할당기 종류
명시적 할당기
• 자원 반환을 명시적으로 요구
예, malloc()/free(), new/delete
묵시적 할당기
• 할당기가 반환을 스스로 판단
예, 가비지 컬렉터
4. 명시적 할당기 요구사항
임의의 요청 순서를 처리
• 할당과 반환의 순서에 대해 가정하지 말 것
요청에 즉시 응답하기
• 요청의 버퍼링, 재정렬 등을 수행하지 못함
힙만 사용
• 할당기 자체 확장성을 위해 사용하는 자료구
조는 힙 자체에
5. 명시적 할당기 요구사항
블록 정렬하기
• 어떤 종류의 데이터도 저장할 수 있어야 함
• 더블워드, 8바이트 경계로 정렬
할당된 블록을 수정하지 않기
• 가용 블록의 수정은 가능하나, 이미 할당된 블
록을 수정해서는 안 됨
그러나, OSX 10.9에서는 Inactive메모리 압축을 도입
하여 시스템 응답성 50%, 웨이크업 속도 40% 향상
7. 가장 쉬운 할당기
구현
• 힙을 하나의 커다란 바이트 배열과 이 배열의
첫 번째 바이트를 가리키는 포인터 p로 구성
• size 바이트를 할당하기 위해 malloc은 현재
p값을 스택에 저장하고 p를 size만큼 증가, p
이전 값을 호출자에 리턴
• free는 아무 것도 하지 않음
특징
• 빠르지만(처리량), 메모리 많이 사용(이용도)
8. 구현상 고민
가용 블록 구성
• 어떻게 가용 블록을 지속적으로 추적하는가
배치
• 새롭게 할당된 블록을 배치하기 위한 가용 블
록을 어떻게 선택하는가?
9. 구현상 고민
분할
• 새롭게 할당한 블록을 가용 블록에 배치한 뒤
에, 가용 블록의 나머지 부분들로 무엇을 할
것인가?
연결
• 방금 반환한 블록으로 무엇을 할 것인가?
10. 묵시적 가용 리스트
Block size 0 0 a
Payload
(allocated block only)
Padding (optional)
8bytes aligned
a = 1: allocated
a = 0: free
The block size includes
the header, payload, and
any padding
malloc returns a pointer
to the beginning of the
payload
8/0 16/1 32/0 16/1 0/1
size(bytes)/allocated bit
18. 블록의 분할과 연결
다시 연결
• 어떻게 바로 뒤 블럭 정보를 알 수 있을까?
8/0 16/1 16/0 16/1 16/1 0/1
8/0 16/1 16/0 16/0 16/1 0/1
?
19. 블록의 분할과 연결
경계 태그
• Knuth가 제안
• 블록의 끝에 푸터를 추가
• 푸터 만큼 오버헤드
8/0 16/1 16/0 16/1 16/1 0/1
8/0 16/1 16/0 16/0 16/1 0/1
Block size 0 0 a
Payload
(allocated block only)
Padding (optional)
Block size 0 0 a
20. 블록의 분할과 연결
경계 태그
• 할당된 블록에서는 푸터 필요 없음
• 대신 앞 블록의 할당여부 플래그 필요
Block size 0 b a
Payload
(allocated block only)
Padding (optional)
Block size 0 b a
Current block
a = 1: allocated
a = 0: free
Previous block
b = 1: allocated
b = 0: free
21. 명시적 가용 리스트
Block size 0 b a
Payload
(allocated block only)
Padding (optional)
Block size 0 b a
Block size 0 b a
Predecessor
Successor
Padding (optional)
Block size 0 b a
allocated block free block
22. 명시적 가용 리스트
할당
• 가용 블럭의 본체 이전, 다음 포인터 저장
• 할당 시간이 first fit의 경우 묵시적과 달리 전
체 블럭 수가 아니라 가용 블럭 수에 비례
23. 명시적 가용 리스트
반환
• 반환하는 블록을 리스트의 시작 부분에 삽입
(LIFO, first fit)
상수 시간에 반환 가능
경계 태그를 이용하면 연결도 상수 시간
• 리스트를 주소 순으로 관리
best fit에 알맞음
24. 분리 가용 리스트
기본 사상
• 할당 요청 받는 크기별로 가용 리스트를 관리
• 그 크기별 묶음을 크기 클래스(size class)라
고 함
• 크기 클래스 정의는
.2의 제곱수: {1}, {2}, {3, 4}, {5-8}, {1025-2048}, ...
.작은 크기는 자신의 크기 클래스로, 큰 블록은 2의
제곱수로: {1},{2}, {3}, {4}, ..., {1023}, {1024},
{1025-2048}, ...
25. 분리 가용 리스트
할당
• 크기 n이 필요할 경우, 적당한 가용 리스트를
검색한 후 크기가 맞는 블록이 없으면 다음 리
스트를 검색
26. 분리 가용 리스트
여러 가지 방법 존재
• 어떻게 크기 클래스를 정의하는가
• 언제 연결을 수행하는가
• 언제 운영체제에 추가적인 힙을 요청하는가
• 분할을 허용할 것인가 등등
27. 간단한 분리 할당기
한 클래스에는 같은 크기의 블럭을
• {17-32}의 경우 리스트에는 모두 32바이트짜
리 블럭
first fit
분할 없음
리스트가 비었을 경우, 운영체제에 추가 메모리 할당
요구(좀 크게)
.받아서 해당 클래스 크기에 맞게 분할해서 리스트
의 맨 앞에 추가
28. 간단한 분리 할당기
한 클래스에는 같은 크기의 블럭을 할당
할당, 반환이 모두 상수 시간
블록당 오버헤드가 거의 없음
• 동일한 크기, 분할 불가, 연결 불가
• 이중 연결 필요 없음: 할당은 first fit, 반환은
맨 앞 삽입
• 다음을 가리키는 포인터만 필요
내외부 단편화에 취약
29. 분리 맞춤(Segregated Fits)
한 클래스에 다른 크기의 블럭을
• first fit 후 남는 것은 분할하여 적당한 크기 클
래스의 리스트에 추가
• 최적 크기 클래스의 리스트가 비었을 경우, 다
음 클래스에 가서 찾음
• 모든 클래스에서 못 찾으면 힙 메모리를 운영
체제에 요청하고 할당 후 분할하여 적절한 크
기 클래스에 추가
• 반환 시 적절한 가용 리스트에 추가
30. 분리 맞춤(Segregated Fits)
한 클래스에 다른 크기의 블럭을
GNU malloc
가용 리스트의 단순한 first fit 검색이 전체 힙을
best fit 검색하는 것을 단순화한 것과 비슷
35. 1024K
A 128K 256K 512K
A B
A C 64K B
Request 100K
Request 240K
Request 64K
36. 1024K
A 128K 256K 512K
A B
A C 64K B
A C B D
Request 100K
Request 240K
Request 64K
Request 256K
37. 1024K
A 128K 256K 512K
A B
A C 64K B
A C B D
A C D
Request 100K
Request 240K
Request 64K
Request 256K
Release B
B를 반환한 다음, 자기의 나머지 반 쪽(buddy) 256K 영역을 확인
그곳이 비어 있다면 합침
현재 A, C가 있어 합치지 않음
38. 1024K
A 128K 256K 512K
A B
A C 64K B
A C B D
A C D
C D
Request 100K
Request 240K
Request 64K
Request 256K
Release B
Release A
39. 1024K
A 128K 256K 512K
A B
A C 64K B
A C B D
A C D
C D
E C D
Request 100K
Request 240K
Request 64K
Request 256K
Release B
Release A
Request 75K
40. 1024K
A 128K 256K 512K
A B
A C 64K B
A C B D
A C D
C D
E C D
E D
Request 100K
Request 240K
Request 64K
Request 256K
Release B
Release A
Request 75K
Release C
C를 반환하고 나머지 반 쪽이 비어 있어 합침
41. 1024K
A 128K 256K 512K
A B
A C 64K B
A C B D
A C D
C D
E C D
E D
D
Request 100K
Request 240K
Request 64K
Request 256K
Release B
Release A
Request 75K
Release C
Release E
E를 반환하고 나머지 반 쪽이 비어합치고 보니 (128K+128K),
합친 것의 반 쪽도 비어 있어 합침 (256K+256K)
42. 1024K
A 128K 256K 512K
A B
A C 64K B
A C B D
A C D
C D
E C D
E D
D
Request 100K
Request 240K
Request 64K
Request 256K
Release B
Release A
Request 75K
Release C
Release E
Release D
45. 버디 시스템
외부 단편화에 대한 해결책
• 1963년 Harry Markowitz가 고안(1990년 노벨
경제학상)
시뮬레이션 랭귀지 프로그래밍 분야에 영향을 미침
SIMSCRIPT라는 언어에 버디 메모리 할당을 도입
• 2의 제곱 단위로 실 할당 크기가 맞아 떨어짐
• 단점
내부 단편화를 해결하지는 못함
62K를 요청하면 64K를 할당 받기 때문에 2K가 낭비
46. 리눅스 커널의 내부 단편화 해결책
슬랩 할당자
• 버디 시스템은 1965년, 슬랩 할당자는 1994년
에 소개
30년...
• 버디 시스템에서 받아온 영역을 내부 단편화
를 최소로 알뜰히 사용하기 위한 방법
47. 슬랩 할당자
기본 원칙
자주 사용하는 자료구조는 할당과 해제가 빈번하므로
캐쉬(이런 할당/해제 패턴은 단편화 유발함)
단편화를 막기 위해 리스트는 연속된 순서대로 정리.
해제하면 해제 리스트로 들어가서 단편화 없음
바로 다음 할당 시 해제 리스트에서 꺼내 사용
할당자가 객체 크기, 페이지 크기, 전체 캐쉬 크기를
알면 보다 정교한 처리가 가능
struct kmem_cache *
kmem_cache_create(const char *name, // 캐시 이름
size_t size, // 캐시에 들어갈 항목의 크기
size_t align, // 정렬 방식
unsigned long flags, // 캐시 동작 제어
void (*ctor)(void*)); // 캐시 생성자
48. align
• SLAB_HWCACHE_ALIGHN
캐쉬 라인에 맞춰 정렬
메모리 사용량 증가
• SLAB_POISON, SLAB_RED_ZONE
struct kmem_cache *
kmem_cache_create(const char *name, // 캐시 이름
size_t size, // 캐시에 들어갈 항목의 크기
size_t align, // 정렬 방식
unsigned long flags, // 캐시 동작 제어
void (*ctor)(void*)); // 캐시 생성자
49. 슬랩 할당자
기본 원칙
프로세서 단위 캐쉬가 있다면 SMP 잠금 없이 할당/
해제 가능
할당자가 NUMA를 지원하는 경우, 메모리를 요청한
노드에 있는 메모리를 할당
여러 객체가 같은 캐쉬에 섞이지 않도록
52. 메모리 할당자 만들기
생각 #1
• 하나의 가용 리스트에서 여러 스레드의 메모
리 할당 요청을 처리하려면 잠금이 필수
• 멀티 스레드 프로세스는 일반적
53. 메모리 할당자 만들기
개선책
• 스레드별로 별도의 가용 리스트를
• 어차피 스레드는 CPU 개수에 따라 효율성이
결정됨
스레드 당 1개가 아닌 스레드 묶음별로 리스트를
• 전체적으로 잠금 경쟁 횟수를 줄일 수 있음
스레드 그룹별로만 잠금 결쟁
54. arena
CPU 1개면 1개
2보다 클 때 CPU개수*4개
small (size class)
[8], [16, 32, 48, ..., 128], [192,
256, 320, ..., 512], [768, 1024,
1280, ..., 3840]
large (size class)
[4K, 8K, 12K, ..., 4072K]
arena
논리적으로 2^k 크기의 chunk로
메모리가 나뉘어져 있음
(기본 크기는 4M)
55. 메모리 할당자 만들기
생각 #2
• 잠금 경쟁이 줄긴 했지만, 한 스레드에서 반복
할 때도 잠금이 필요
56. 메모리 할당자 만들기
개선책
• 스레드 1개에 각각 작은 별도의 가용 리스트
캐쉬를 두어
캐쉬에 여유가 있는한 잠금없이 메모리 취득 가능
57. 메모리 할당자 만들기
캐쉬가 크면, 특정 경
우에는 좋지만 일반
적으로 단편화가 발
생하여 좋지 않을 수
있음
단편화를 제한하기
위해, 캐쉬에 대해 점
증 적 GC를 수행
한 번이상 GC 수행할
동안에 사용되지 않
은 캐쉬된 객체는 그
양에 비례하여 arena
로 점차 옮겨짐
tcache
10~100배의 싱크 이벤트 감소 효과