가상→물리 주소 변환 결과를 담아 두는 CPU 내부의 작은 캐시 (Translation Lookaside Buffer).
왜 필요한가 — 변환이 공짜가 아니다
페이지 테이블은 메모리에 있다. 그래서 주소를 변환하려면 메모리를 읽어야 한다.
- 데이터 하나 읽기 = ① 페이지 테이블 읽기(메모리 접근) + ② 실제 데이터 읽기(메모리 접근)
- 메모리 접근이 2배
게다가 x86-64는 페이지 테이블이 4단계라 변환에만 메모리 접근이 4번이다.
- 데이터 1번 읽는 데 메모리 접근 5번 — ← 그대로 두면 5배 느린 컴퓨터
TLB는 이 변환 결과를 캐싱해 ①을 없앤다.
동작
CPU: 가상 주소 0x1234_5000 접근
↓
TLB 확인 → 있음(TLB 히트, ~1 사이클) → 물리 주소 즉시 획득
→ 없음(TLB 미스) → 페이지 테이블을 4단계 순회 → TLB에 저장 → 진행
TLB는 매우 작다(수십~수천 항목). 대신 완전 연관 방식으로 병렬 비교해 1 사이클 안에 답한다.
히트율이 왜 그렇게 높은가
TLB 항목이 1000개뿐인데 히트율이 99%를 넘는다. 페이지 단위로 캐싱하기 때문이다.
TLB 항목 1개 = 페이지 1개 = 4KB 커버 1000개 × 4KB = 4MB 어치의 주소 공간을 커버
프로그램이 당장 쓰는 영역은 대개 이 안에 들어온다 (지역성)
컨텍스트 스위칭에서 TLB가 중요한 이유
프로세스가 바뀌면 주소 공간이 달라진다 — 같은 가상 주소가 다른 물리 주소를 뜻한다. 그래서 옛 항목을 그대로 두면 잘못된 메모리를 읽는다.
- 전통적 방식: 프로세스 전환 시 TLB 전체 무효화(flush)
- 전환 직후 한동안 TLB 미스가 폭발
- 이것이 프로세스 전환이 스레드 전환보다 비싼 핵심 이유
현대 CPU는 ASID/PCID(주소 공간 식별자)를 항목에 붙여, 전체를 비우지 않고 자기 것만 골라 쓸 수 있게 한다.
스레드 전환은 주소 공간이 같아 TLB를 비울 필요가 없다.
Huge Page — 실무 튜닝 포인트
페이지를 4KB 대신 2MB로 쓰면 항목 하나가 커버하는 범위가 500배 늘어난다.
- 4KB 페이지: 1000 항목 × 4KB — = 4MB 커버
- 2MB 페이지: 1000 항목 × 2MB — = 2GB 커버 ← TLB 미스가 급감
힙이 큰 JVM(수십 GB)에서 효과가 크다.
-XX:+UseLargePages
다만 Transparent Huge Pages(THP)는 지연 시간이 튀는 문제로 유명하다 — 큰 연속 공간을 확보하려고 메모리를 압축(compaction)하는 동안 멈춘다. 그래서 Redis·MongoDB·Kafka 문서는 THP를 끄라고 권고한다.
echo never > /sys/kernel/mm/transparent_hugepage/enabled
이 한 줄이 여러 DB 설치 가이드에 등장하는 이유다.