Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
메모리 할당에 관한 기초
cybaek@nhnent.com
cybaek@me.com
cybaek@naver.com
2013.8.10
동적 메모리 할당기
힙(Heap)을 관리
할당기 종류
명시적 할당기
• 자원 반환을 명시적으로 요구
예, malloc()/free(), new/delete
묵시적 할당기
• 할당기가 반환을 스스로 판단
예, 가비지 컬렉터
명시적 할당기 요구사항
임의의 요청 순서를 처리
• 할당과 반환의 순서에 대해 가정하지 말 것
요청에 즉시 응답하기
• 요청의 버퍼링, 재정렬 등을 수행하지 못함
힙만 사용
• 할당기 자체 확장성을 위해 사용하는 자료구...
명시적 할당기 요구사항
블록 정렬하기
• 어떤 종류의 데이터도 저장할 수 있어야 함
• 더블워드, 8바이트 경계로 정렬
할당된 블록을 수정하지 않기
• 가용 블록의 수정은 가능하나, 이미 할당된 블
록을 수정해서는 안 ...
명시적 할당기의 구현 목표
처리량 극대화
메모리 이용도 극대화
가장 쉬운 할당기
구현
• 힙을 하나의 커다란 바이트 배열과 이 배열의
첫 번째 바이트를 가리키는 포인터 p로 구성
• size 바이트를 할당하기 위해 malloc은 현재
p값을 스택에 저장하고 p를 size만큼 증가,...
구현상 고민
가용 블록 구성
• 어떻게 가용 블록을 지속적으로 추적하는가
배치
• 새롭게 할당된 블록을 배치하기 위한 가용 블
록을 어떻게 선택하는가?
구현상 고민
분할
• 새롭게 할당한 블록을 가용 블록에 배치한 뒤
에, 가용 블록의 나머지 부분들로 무엇을 할
것인가?
연결
• 방금 반환한 블록으로 무엇을 할 것인가?
묵시적 가용 리스트
Block size 0 0 a
Payload
(allocated block only)
Padding (optional)
8bytes aligned
a = 1: allocated
a = 0: free
...
블록의 배치
내부 단편화
8/0 16/1 32/0 16/1 0/1
malloc(13)
블록의 배치
외부 단편화
8/0 16/1 32/0 16/1 0/1
malloc(8+32)
블록 배치 전략
first fit
• 첫 번째로 매치하는 것을
• 큰 블록은 뒤에 남는 경향이 있음
• 이로 인해 큰 블록을 할당하는데 상대적으로
많은 시간이 걸릴 수 있음
best fit
• 가장 잘 맞는 것
• 좋지...
블록의 배치 전략
next fit
• first fit의 대안으로 Knuth가 제안
• 목록의 앞에 작은 블록이 있다면 first fit 보다
많이 빠름
• 하지만 일부 연구에서 최악의 메모리 이용 결
과가
블록의 분할과 연결
분할
8/0 16/1 32/0 16/1 0/1
8/0 16/1 16/1 16/0 16/1 0/1
블록의 분할과 연결
연결
8/0 16/1 32/0 16/1 0/1
8/0 16/1 16/1 16/0 16/1 0/1
8/0 16/1 16/0 16/0 16/1 0/1
8/0 16/1 32/0 16/1 0/1
while ...
블록의 분할과 연결
스래싱(thrashing)
• 분할과 연결의 반복
8/0 16/1 32/0 16/1 0/1
8/0 16/1 16/1 16/0 16/1 0/1
8/0 16/1 16/0 16/0 16/1 0/1
8/0 ...
블록의 분할과 연결
다시 연결
• 어떻게 바로 뒤 블럭 정보를 알 수 있을까?
8/0 16/1 16/0 16/1 16/1 0/1
8/0 16/1 16/0 16/0 16/1 0/1
?
블록의 분할과 연결
경계 태그
• 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 si...
블록의 분할과 연결
경계 태그
• 할당된 블록에서는 푸터 필요 없음
• 대신 앞 블록의 할당여부 플래그 필요
Block size 0 b a
Payload
(allocated block only)
Padding (opti...
명시적 가용 리스트
Block size 0 b a
Payload
(allocated block only)
Padding (optional)
Block size 0 b a
Block size 0 b a
Predecesso...
명시적 가용 리스트
할당
• 가용 블럭의 본체 이전, 다음 포인터 저장
• 할당 시간이 first fit의 경우 묵시적과 달리 전
체 블럭 수가 아니라 가용 블럭 수에 비례
명시적 가용 리스트
반환
• 반환하는 블록을 리스트의 시작 부분에 삽입
(LIFO, first fit)
상수 시간에 반환 가능
경계 태그를 이용하면 연결도 상수 시간
• 리스트를 주소 순으로 관리
best fit에 알맞음
분리 가용 리스트
기본 사상
• 할당 요청 받는 크기별로 가용 리스트를 관리
• 그 크기별 묶음을 크기 클래스(size class)라
고 함
• 크기 클래스 정의는
.2의 제곱수: {1}, {2}, {3, 4}, {5-...
분리 가용 리스트
할당
• 크기 n이 필요할 경우, 적당한 가용 리스트를
검색한 후 크기가 맞는 블록이 없으면 다음 리
스트를 검색
분리 가용 리스트
여러 가지 방법 존재
• 어떻게 크기 클래스를 정의하는가
• 언제 연결을 수행하는가
• 언제 운영체제에 추가적인 힙을 요청하는가
• 분할을 허용할 것인가 등등
간단한 분리 할당기
한 클래스에는 같은 크기의 블럭을
• {17-32}의 경우 리스트에는 모두 32바이트짜
리 블럭
first fit
분할 없음
리스트가 비었을 경우, 운영체제에 추가 메모리 할당
요구(좀 크게)
.받아...
간단한 분리 할당기
한 클래스에는 같은 크기의 블럭을 할당
할당, 반환이 모두 상수 시간
블록당 오버헤드가 거의 없음
• 동일한 크기, 분할 불가, 연결 불가
• 이중 연결 필요 없음: 할당은 first fit, 반환은...
분리 맞춤(Segregated Fits)
한 클래스에 다른 크기의 블럭을
• first fit 후 남는 것은 분할하여 적당한 크기 클
래스의 리스트에 추가
• 최적 크기 클래스의 리스트가 비었을 경우, 다
음 클래스에 ...
분리 맞춤(Segregated Fits)
한 클래스에 다른 크기의 블럭을
GNU malloc
가용 리스트의 단순한 first fit 검색이 전체 힙을
best fit 검색하는 것을 단순화한 것과 비슷
리눅스 커널의 외부 단편화 해결책
버디 시스템
• 2의 제곱 단위로 메모리를 할당
1024K
사용할 수 있는 가장 큰 블록을 하나 할당 받아
그 블록을 요청 받은 크기에 따라 적당히 나눠 사용
나눌 때는 블록을 절반씩 나눔
1024K
A 128K 256K 512KRequest 100K
1024K를 절반으로 나누면서
요청 받은 100K에 가장 적합한 블록을 찾음
512K는 100K에 비해 너무 커, 다시 나눔
이 과정을 반복
1024K
A 128K 256K 512K
A B
Request 100K
Request 240K
1024K
A 128K 256K 512K
A B
A C 64K B
Request 100K
Request 240K
Request 64K
1024K
A 128K 256K 512K
A B
A C 64K B
A C B D
Request 100K
Request 240K
Request 64K
Request 256K
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를 반환한 다음,...
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
Releas...
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
...
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
Releas...
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
Rele...
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
Rele...
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
E C D
64K
128K
256K
512K
1024K
버디 시스템
외부 단편화에 대한 해결책
• 1963년 Harry Markowitz가 고안(1990년 노벨
경제학상)
시뮬레이션 랭귀지 프로그래밍 분야에 영향을 미침
SIMSCRIPT라는 언어에 버디 메모리 할당을 도입
...
리눅스 커널의 내부 단편화 해결책
슬랩 할당자
• 버디 시스템은 1965년, 슬랩 할당자는 1994년
에 소개
30년...
• 버디 시스템에서 받아온 영역을 내부 단편화
를 최소로 알뜰히 사용하기 위한 방법
슬랩 할당자
기본 원칙
자주 사용하는 자료구조는 할당과 해제가 빈번하므로
캐쉬(이런 할당/해제 패턴은 단편화 유발함)
단편화를 막기 위해 리스트는 연속된 순서대로 정리.
해제하면 해제 리스트로 들어가서 단편화 없음
바로...
align
• SLAB_HWCACHE_ALIGHN
캐쉬 라인에 맞춰 정렬
메모리 사용량 증가
• SLAB_POISON, SLAB_RED_ZONE
struct kmem_cache *
kmem_cache_create(con...
슬랩 할당자
기본 원칙
프로세서 단위 캐쉬가 있다면 SMP 잠금 없이 할당/
해제 가능
할당자가 NUMA를 지원하는 경우, 메모리를 요청한
노드에 있는 메모리를 할당
여러 객체가 같은 캐쉬에 섞이지 않도록
슬랩 할당자
캐쉬
슬랩
슬랩
객체
객체
객체
객체
물리적으로 연속된 페이지
memcached의 슬랩 할당자
-m 1 1MB page pool
-l 1k 1024 bytes per page
메모리 할당자 만들기
생각 #1
• 하나의 가용 리스트에서 여러 스레드의 메모
리 할당 요청을 처리하려면 잠금이 필수
• 멀티 스레드 프로세스는 일반적
메모리 할당자 만들기
개선책
• 스레드별로 별도의 가용 리스트를
• 어차피 스레드는 CPU 개수에 따라 효율성이
결정됨
스레드 당 1개가 아닌 스레드 묶음별로 리스트를
• 전체적으로 잠금 경쟁 횟수를 줄일 수 있음
스레...
arena
CPU 1개면 1개
2보다 클 때 CPU개수*4개
small (size class)
[8], [16, 32, 48, ..., 128], [192,
256, 320, ..., 512], [768, 1024,
1...
메모리 할당자 만들기
생각 #2
• 잠금 경쟁이 줄긴 했지만, 한 스레드에서 반복
할 때도 잠금이 필요
메모리 할당자 만들기
개선책
• 스레드 1개에 각각 작은 별도의 가용 리스트
캐쉬를 두어
캐쉬에 여유가 있는한 잠금없이 메모리 취득 가능
메모리 할당자 만들기
캐쉬가 크면, 특정 경
우에는 좋지만 일반
적으로 단편화가 발
생하여 좋지 않을 수
있음
단편화를 제한하기
위해, 캐쉬에 대해 점
증 적 GC를 수행
한 번이상 GC 수행할
동안에 사용되지 않
은 ...
페이스북의 jemalloc
Upcoming SlideShare
Loading in …5
×

메모리 할당에 관한 기초

11,212 views

Published on

메모리 할당과 관련한 내용입니다.

Published in: Software
  • Thanks for share your idea, We have also maintain a slide side of our company CPH Graphics Media - www.clippingpathhouse.com You may visit our site will be help by any way.
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • 함께 협업서비스를 개발할 분을 찾습니다. * 기획자: 1명 * 프론트 개발자: 1명 * 백엔드 개발자: 1명 개발환경과 도구는 Angular.js, Grunt, Java8, Spring4, JPA, Netty4, Vagrant, IntelliJ, GitHub입니다. 단언컨데, 최소한 우리나라에서 가장 스케일이 크고 비전이 있는 프로젝트입니다. 정말 내가 필요한 그런 서비스를 만들고 있습니다. 10월 1일 프로젝트를 시작해서 만 한 달만에 저희가 만들고 있는 툴을 독푸딩하며, 배포는 오늘 아침까지 1292번을 했습니다. 함께 할 분을 찾습니다. ‪#‎NHN엔터테인먼트‬
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • @Kwangsik Chae 고맙습니다 ^^
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • 재미있게 봤습니다 ^^
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

메모리 할당에 관한 기초

  1. 1. 메모리 할당에 관한 기초 cybaek@nhnent.com cybaek@me.com cybaek@naver.com 2013.8.10
  2. 2. 동적 메모리 할당기 힙(Heap)을 관리
  3. 3. 할당기 종류 명시적 할당기 • 자원 반환을 명시적으로 요구 예, malloc()/free(), new/delete 묵시적 할당기 • 할당기가 반환을 스스로 판단 예, 가비지 컬렉터
  4. 4. 명시적 할당기 요구사항 임의의 요청 순서를 처리 • 할당과 반환의 순서에 대해 가정하지 말 것 요청에 즉시 응답하기 • 요청의 버퍼링, 재정렬 등을 수행하지 못함 힙만 사용 • 할당기 자체 확장성을 위해 사용하는 자료구 조는 힙 자체에
  5. 5. 명시적 할당기 요구사항 블록 정렬하기 • 어떤 종류의 데이터도 저장할 수 있어야 함 • 더블워드, 8바이트 경계로 정렬 할당된 블록을 수정하지 않기 • 가용 블록의 수정은 가능하나, 이미 할당된 블 록을 수정해서는 안 됨 그러나, OSX 10.9에서는 Inactive메모리 압축을 도입 하여 시스템 응답성 50%, 웨이크업 속도 40% 향상
  6. 6. 명시적 할당기의 구현 목표 처리량 극대화 메모리 이용도 극대화
  7. 7. 가장 쉬운 할당기 구현 • 힙을 하나의 커다란 바이트 배열과 이 배열의 첫 번째 바이트를 가리키는 포인터 p로 구성 • size 바이트를 할당하기 위해 malloc은 현재 p값을 스택에 저장하고 p를 size만큼 증가, p 이전 값을 호출자에 리턴 • free는 아무 것도 하지 않음 특징 • 빠르지만(처리량), 메모리 많이 사용(이용도)
  8. 8. 구현상 고민 가용 블록 구성 • 어떻게 가용 블록을 지속적으로 추적하는가 배치 • 새롭게 할당된 블록을 배치하기 위한 가용 블 록을 어떻게 선택하는가?
  9. 9. 구현상 고민 분할 • 새롭게 할당한 블록을 가용 블록에 배치한 뒤 에, 가용 블록의 나머지 부분들로 무엇을 할 것인가? 연결 • 방금 반환한 블록으로 무엇을 할 것인가?
  10. 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
  11. 11. 블록의 배치 내부 단편화 8/0 16/1 32/0 16/1 0/1 malloc(13)
  12. 12. 블록의 배치 외부 단편화 8/0 16/1 32/0 16/1 0/1 malloc(8+32)
  13. 13. 블록 배치 전략 first fit • 첫 번째로 매치하는 것을 • 큰 블록은 뒤에 남는 경향이 있음 • 이로 인해 큰 블록을 할당하는데 상대적으로 많은 시간이 걸릴 수 있음 best fit • 가장 잘 맞는 것 • 좋지만, 힙 전체를 검색해야함
  14. 14. 블록의 배치 전략 next fit • first fit의 대안으로 Knuth가 제안 • 목록의 앞에 작은 블록이 있다면 first fit 보다 많이 빠름 • 하지만 일부 연구에서 최악의 메모리 이용 결 과가
  15. 15. 블록의 분할과 연결 분할 8/0 16/1 32/0 16/1 0/1 8/0 16/1 16/1 16/0 16/1 0/1
  16. 16. 블록의 분할과 연결 연결 8/0 16/1 32/0 16/1 0/1 8/0 16/1 16/1 16/0 16/1 0/1 8/0 16/1 16/0 16/0 16/1 0/1 8/0 16/1 32/0 16/1 0/1 while (...) { p = malloc(16) // ... free(p) }
  17. 17. 블록의 분할과 연결 스래싱(thrashing) • 분할과 연결의 반복 8/0 16/1 32/0 16/1 0/1 8/0 16/1 16/1 16/0 16/1 0/1 8/0 16/1 16/0 16/0 16/1 0/1 8/0 16/1 32/0 16/1 0/1 while (...) { p = malloc(16) // ... free(p) }
  18. 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. 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. 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. 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. 22. 명시적 가용 리스트 할당 • 가용 블럭의 본체 이전, 다음 포인터 저장 • 할당 시간이 first fit의 경우 묵시적과 달리 전 체 블럭 수가 아니라 가용 블럭 수에 비례
  23. 23. 명시적 가용 리스트 반환 • 반환하는 블록을 리스트의 시작 부분에 삽입 (LIFO, first fit) 상수 시간에 반환 가능 경계 태그를 이용하면 연결도 상수 시간 • 리스트를 주소 순으로 관리 best fit에 알맞음
  24. 24. 분리 가용 리스트 기본 사상 • 할당 요청 받는 크기별로 가용 리스트를 관리 • 그 크기별 묶음을 크기 클래스(size class)라 고 함 • 크기 클래스 정의는 .2의 제곱수: {1}, {2}, {3, 4}, {5-8}, {1025-2048}, ... .작은 크기는 자신의 크기 클래스로, 큰 블록은 2의 제곱수로: {1},{2}, {3}, {4}, ..., {1023}, {1024}, {1025-2048}, ...
  25. 25. 분리 가용 리스트 할당 • 크기 n이 필요할 경우, 적당한 가용 리스트를 검색한 후 크기가 맞는 블록이 없으면 다음 리 스트를 검색
  26. 26. 분리 가용 리스트 여러 가지 방법 존재 • 어떻게 크기 클래스를 정의하는가 • 언제 연결을 수행하는가 • 언제 운영체제에 추가적인 힙을 요청하는가 • 분할을 허용할 것인가 등등
  27. 27. 간단한 분리 할당기 한 클래스에는 같은 크기의 블럭을 • {17-32}의 경우 리스트에는 모두 32바이트짜 리 블럭 first fit 분할 없음 리스트가 비었을 경우, 운영체제에 추가 메모리 할당 요구(좀 크게) .받아서 해당 클래스 크기에 맞게 분할해서 리스트 의 맨 앞에 추가
  28. 28. 간단한 분리 할당기 한 클래스에는 같은 크기의 블럭을 할당 할당, 반환이 모두 상수 시간 블록당 오버헤드가 거의 없음 • 동일한 크기, 분할 불가, 연결 불가 • 이중 연결 필요 없음: 할당은 first fit, 반환은 맨 앞 삽입 • 다음을 가리키는 포인터만 필요 내외부 단편화에 취약
  29. 29. 분리 맞춤(Segregated Fits) 한 클래스에 다른 크기의 블럭을 • first fit 후 남는 것은 분할하여 적당한 크기 클 래스의 리스트에 추가 • 최적 크기 클래스의 리스트가 비었을 경우, 다 음 클래스에 가서 찾음 • 모든 클래스에서 못 찾으면 힙 메모리를 운영 체제에 요청하고 할당 후 분할하여 적절한 크 기 클래스에 추가 • 반환 시 적절한 가용 리스트에 추가
  30. 30. 분리 맞춤(Segregated Fits) 한 클래스에 다른 크기의 블럭을 GNU malloc 가용 리스트의 단순한 first fit 검색이 전체 힙을 best fit 검색하는 것을 단순화한 것과 비슷
  31. 31. 리눅스 커널의 외부 단편화 해결책 버디 시스템 • 2의 제곱 단위로 메모리를 할당
  32. 32. 1024K 사용할 수 있는 가장 큰 블록을 하나 할당 받아 그 블록을 요청 받은 크기에 따라 적당히 나눠 사용 나눌 때는 블록을 절반씩 나눔
  33. 33. 1024K A 128K 256K 512KRequest 100K 1024K를 절반으로 나누면서 요청 받은 100K에 가장 적합한 블록을 찾음 512K는 100K에 비해 너무 커, 다시 나눔 이 과정을 반복
  34. 34. 1024K A 128K 256K 512K A B Request 100K Request 240K
  35. 35. 1024K A 128K 256K 512K A B A C 64K B Request 100K Request 240K Request 64K
  36. 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. 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. 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. 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. 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. 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. 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
  43. 43. 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
  44. 44. E C D 64K 128K 256K 512K 1024K
  45. 45. 버디 시스템 외부 단편화에 대한 해결책 • 1963년 Harry Markowitz가 고안(1990년 노벨 경제학상) 시뮬레이션 랭귀지 프로그래밍 분야에 영향을 미침 SIMSCRIPT라는 언어에 버디 메모리 할당을 도입 • 2의 제곱 단위로 실 할당 크기가 맞아 떨어짐 • 단점 내부 단편화를 해결하지는 못함 62K를 요청하면 64K를 할당 받기 때문에 2K가 낭비
  46. 46. 리눅스 커널의 내부 단편화 해결책 슬랩 할당자 • 버디 시스템은 1965년, 슬랩 할당자는 1994년 에 소개 30년... • 버디 시스템에서 받아온 영역을 내부 단편화 를 최소로 알뜰히 사용하기 위한 방법
  47. 47. 슬랩 할당자 기본 원칙 자주 사용하는 자료구조는 할당과 해제가 빈번하므로 캐쉬(이런 할당/해제 패턴은 단편화 유발함) 단편화를 막기 위해 리스트는 연속된 순서대로 정리. 해제하면 해제 리스트로 들어가서 단편화 없음 바로 다음 할당 시 해제 리스트에서 꺼내 사용 할당자가 객체 크기, 페이지 크기, 전체 캐쉬 크기를 알면 보다 정교한 처리가 가능 struct kmem_cache * kmem_cache_create(const char *name, // 캐시 이름 size_t size, // 캐시에 들어갈 항목의 크기 size_t align, // 정렬 방식 unsigned long flags, // 캐시 동작 제어 void (*ctor)(void*)); // 캐시 생성자
  48. 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. 49. 슬랩 할당자 기본 원칙 프로세서 단위 캐쉬가 있다면 SMP 잠금 없이 할당/ 해제 가능 할당자가 NUMA를 지원하는 경우, 메모리를 요청한 노드에 있는 메모리를 할당 여러 객체가 같은 캐쉬에 섞이지 않도록
  50. 50. 슬랩 할당자 캐쉬 슬랩 슬랩 객체 객체 객체 객체 물리적으로 연속된 페이지
  51. 51. memcached의 슬랩 할당자 -m 1 1MB page pool -l 1k 1024 bytes per page
  52. 52. 메모리 할당자 만들기 생각 #1 • 하나의 가용 리스트에서 여러 스레드의 메모 리 할당 요청을 처리하려면 잠금이 필수 • 멀티 스레드 프로세스는 일반적
  53. 53. 메모리 할당자 만들기 개선책 • 스레드별로 별도의 가용 리스트를 • 어차피 스레드는 CPU 개수에 따라 효율성이 결정됨 스레드 당 1개가 아닌 스레드 묶음별로 리스트를 • 전체적으로 잠금 경쟁 횟수를 줄일 수 있음 스레드 그룹별로만 잠금 결쟁
  54. 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. 55. 메모리 할당자 만들기 생각 #2 • 잠금 경쟁이 줄긴 했지만, 한 스레드에서 반복 할 때도 잠금이 필요
  56. 56. 메모리 할당자 만들기 개선책 • 스레드 1개에 각각 작은 별도의 가용 리스트 캐쉬를 두어 캐쉬에 여유가 있는한 잠금없이 메모리 취득 가능
  57. 57. 메모리 할당자 만들기 캐쉬가 크면, 특정 경 우에는 좋지만 일반 적으로 단편화가 발 생하여 좋지 않을 수 있음 단편화를 제한하기 위해, 캐쉬에 대해 점 증 적 GC를 수행 한 번이상 GC 수행할 동안에 사용되지 않 은 캐쉬된 객체는 그 양에 비례하여 arena 로 점차 옮겨짐 tcache 10~100배의 싱크 이벤트 감소 효과
  58. 58. 페이스북의 jemalloc

×