운영체제 용어 사전
가상 메모리Translation Lookaside Buffer · TLB 미스

TLB

주소 변환 결과를 캐싱하는 하드웨어. 없으면 메모리 접근마다 페이지 테이블을 여러 번 읽어야 한다.

주소 변환 결과를 캐싱하는 작고 빠른 하드웨어 캐시.

없으면 어떻게 되나

다단계 페이지 테이블에서 주소 하나를 변환하려면

  • 각 단계의 테이블을 메모리에서 읽어야 한다 (4단계면 4번)
  • 실제 데이터를 읽는 건 그다음이니 총 5번

메모리 접근 한 번이 다섯 번이 된다 → 감당이 안 된다

TLB가 하는 일

[페이지 번호 → 프레임 번호] 쌍을 수십~수백 개 캐싱한다

  • TLB 히트 — → 즉시 변환 (1 사이클 수준)
  • TLB 미스 — → 페이지 테이블을 걸어 내려간다 (page table walk) 후 TLB 에 채운다

적중률이 보통 99% 를 넘는다 — 지역성 덕분이다

"작은데 왜 잘 맞나" — 프로그램이 같은 페이지를 반복해서 쓰기 때문이다(공간 지역성). 4KB 페이지 하나에 코드나 데이터가 꽤 많이 들어간다.

컨텍스트 스위치와의 관계

프로세스가 바뀌면 주소 변환 규칙 자체가 달라진다

  • 예전에는 TLB 를 통째로 비웠다 (플러시)
  • 전환 직후 TLB 미스가 쏟아진다 → 컨텍스트 스위치 간접 비용의 큰 부분

ASID/PCID

  • TLB 항목에 주소 공간 식별자를 붙인다
  • 프로세스가 바뀌어도 전부 버리지 않아도 된다

성능 문제로 드러나는 모습

증상: 데이터를 넓게 흩어 접근하는 워크로드가 유독 느리다

  • (큰 해시 테이블 무작위 접근 · 포인터를 따라가는 자료구조)

원인: 접근할 때마다 다른 페이지 → TLB 미스 → page table walk

처방: 데이터를 모아 배치한다 (배열이 연결 리스트보다 빠른 이유의 일부)

  • Huge Page 로 페이지 수를 줄인다
perf stat -e dTLB-load-misses,iTLB-load-misses ./app

캐시 계층 안에서의 위치

  • CPU 레지스터 — < 1 사이클

  • L1 캐시 · TLB — 수 사이클

  • L2 캐시 — 수십 사이클

  • L3 캐시 — 수십~백 사이클

  • 메인 메모리 — 수백 사이클

  • 디스크(SSD) — 수만~수십만 사이클

  • TLB 미스는 '메인 메모리를 여러 번 읽는 것' 이라 체감 비용이 크다

면접 함정

  • "TLB는 데이터를 캐싱한다"주소 변환 결과를 캐싱한다. 데이터는 L1/L2/L3의 몫이다.
  • "TLB 미스는 페이지 폴트" → 다르다. TLB 미스는 테이블에 있고, 페이지 폴트는 메모리에 없는 것이다.

크기와 구조

보통 L1 TLB 수십~수백 항목, L2 TLB 수천 항목 명령용(iTLB)과 데이터용(dTLB)이 분리돼 있다

4KB 페이지 · 항목 1,536개면 커버 범위는 약 6MB

  • 워킹셋이 그보다 크면 TLB 미스가 늘기 시작한다

"메모리는 충분한데 왜 느리지" 의 답이 여기일 때가 있다 — 용량이 아니라 접근 범위가 문제다.

Huge Page의 효과

2MB 페이지를 쓰면 같은 항목 수로 512배 넓은 범위를 덮는다

  • 1,536 × 2MB = 약 3GB

큰 힙을 쓰는 DB · 인메모리 캐시에서 수 % ~ 수십 % 개선 사례가 있다

cat /sys/kernel/mm/transparent_hugepage/enabled
# [always] madvise never

# THP(투명 huge page)는 자동이지만 부작용도 있다
#   할당 지연 스파이크 · 메모리 낭비
#   → DB 벤더들이 흔히 never 나 madvise 를 권장한다

보안과의 접점

Meltdown 취약점 대응으로 커널과 유저의 페이지 테이블을 분리했다 (KPTI)
  → 시스템 콜마다 페이지 테이블을 바꾼다 → TLB 플러시
  → 시스템 콜이 잦은 워크로드에서 성능이 눈에 띄게 떨어졌다
  → PCID 를 지원하는 CPU 에서는 손실이 크게 줄어든다

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — 가상 메모리 — 페이징·TLB·페이지 폴트