에듀테크 프로젝트 대시보드
TLB (Translation Lookaside Buffer)
가상 메모리 & 페이징에서 CPU가 쓰는 모든 주소가 페이지 테이블을 거쳐 물리 주소로 바뀐다는 걸 배웠다. 문제는 그 페이지 테이블도 결국 메모리(RAM) 안에 있다는 것 — 그래서 이번엔 그 변환 자체를 캐시 메모리 매핑에서 배운 방식으로 캐싱하는 TLB(Translation Lookaside Buffer)를 다룬다.
프로그램이 읽으려는 데이터 하나에 접근하려면, 실제로는 메모리에 두 번 접근해야 한다.
캐시 메모리 매핑에서 배운 캐시는 "자주 쓰는 데이터를 CPU 가까이 작은 초고속 메모리에 복사해 둔다"는 아이디어였다. TLB는 정확히 같은 아이디어를 데이터가 아니라 주소 변환 결과(가상 페이지 번호 VPN → 물리 프레임 번호 PFN)에 적용한 것이다.
아래 시뮬레이터에서는 이 축소 모델(8비트 가상주소)을 쓴다. TLB가 캐싱하는 건 VPN 부분뿐 — offset은 원래 그대로 붙는다.
가상 페이지 번호(VPN)를 하나씩 조회한다. TLB 히트면 초록으로 즉시 끝나고, TLB 미스면 빨간색으로 표시된 뒤 아래 페이지 테이블까지 가서 찾아오고 TLB에 새로 채운다(4칸이 꽉 차면 가장 오래된 항목 축출, LRU).
지금까지는 페이지 테이블이 한 단계(1-level)라서 TLB 미스가 나도 메모리 접근이 딱 1번만 추가됐다. 그런데 64비트 주소공간에서는 페이지 테이블 하나를 통짜 배열로 두면 크기가 감당이 안 돼서, 실제로는 여러 단계의 트리로 쪼갠다(가상 메모리 & 페이징 — 다단계 페이지 테이블 참고). 문제는 TLB 미스가 나면 이 트리를 뿌리부터 끝까지 전부 훑어야 한다는 것.
| 구조 | TLB 미스 시 추가 메모리 접근 |
|---|---|
| 1단계 페이지 테이블(이 페이지의 시뮬레이터) | 1회 |
| x86 32비트, 2단계 페이징 | 최대 2회 |
| x86-64, 4단계 페이징(PML4 → PDPT → PD → PT) | 최대 4회 |
| 5단계 페이징(최신 대용량 주소공간) | 최대 5회 |
TLB에 저장된 (VPN → PFN) 매핑은 특정 프로세스의 가상 주소공간을 전제로 한다. 그런데 OS가 다른 프로세스로 컨텍스트 스위칭을 하면 가상 주소공간 자체가 바뀐다 — 프로세스 A의 VPN 3과 프로세스 B의 VPN 3은 완전히 다른 물리 페이지를 가리킨다.
가장 단순한 방법은 프로세스가 바뀔 때마다 TLB를 통째로 비우는 것(flush)이다. 안전하지만, 새 프로세스가 실행을 재개한 직후엔 TLB가 텅 비어 있어 한동안 미스가 쏟아진다(콜드 스타트).
이를 완화하려고 실제 CPU들은 TLB 항목에 ASID(Address Space ID)라는 프로세스 식별자를 같이 저장한다. 그러면 컨텍스트 스위칭이 일어나도 TLB를 비우지 않고, "이 항목은 프로세스 7 것"이라는 태그로 구분해 두었다가 필요한 것만 골라 쓸 수 있다.
TLB를 아주 단순화하면 결국 고정 용량 dict + LRU 축출이다. 캐시 매핑 페이지의 LRU 축출과 개념이 동일하다.
# 아주 단순화한 TLB 흉내: dict + LRU 축출 from collections import OrderedDict class TLB: def __init__(self, capacity=4): self.capacity = capacity self.table = OrderedDict() # vpn -> pfn def access(self, vpn, page_table): if vpn in self.table: self.table.move_to_end(vpn) # 방금 썼으니 MRU로 갱신 return self.table[vpn], "HIT" # 메모리 접근 1회로 끝 pfn = page_table[vpn] # TLB 미스 → 페이지 테이블 walk (메모리 접근 +1회) if len(self.table) >= self.capacity: self.table.popitem(last=False) # 가장 오래 안 쓴 항목 축출 self.table[vpn] = pfn return pfn, "MISS"
위 시뮬레이터가 하는 일이 정확히 이거다 — table이 TLB 4칸, page_table이 메모리 위의 진짜 페이지 테이블 16칸.