Memory / Cache
메모리와 캐시
CPU는 RAM보다 훨씬 빠르기 때문에, 자주 쓰는 데이터를 L1·L2·L3 캐시에 두어 대기 시간을 줄인다.
메모리는 두 축으로 이해해야 한다. 첫째는 '속도-용량-비용'의 트레이드오프로 배열된 물리적 메모리 계층(memory hierarchy)이고, 둘째는 하나의 프로세스가 바라보는 논리적 가상 메모리 레이아웃(virtual memory layout)이다. 계층은 위에서부터 레지스터(1클럭)→L1 캐시(~1ns)→L2(~4ns)→L3(공유, ~10~40ns)→RAM(~100ns)→SSD(수십 µs)→HDD(수 ms) 순으로, 위로 갈수록 빠르지만 비싸고 작으며, 자주 쓰는 데이터를 상위 계층이 붙잡아 지역성(locality)을 활용해 평균 접근 시간을 줄인다. 한편 각 프로세스는 자신만의 연속된 가상 주소 공간을 갖는데, 낮은 주소부터 코드(Text)·데이터(Data)·BSS·힙(Heap, 위로 성장)·메모리 매핑 영역·스택(Stack, 아래로 성장)이 배치되고, 상위 절반은 커널 영역(kernel space)으로 사용자 코드가 접근할 수 없다. 이 가상 주소를 실제 물리 주소로 바꾸는 하드웨어가 MMU(메모리 관리 장치)이며, 페이지 테이블(page table)을 참조해 페이징(paging)을 수행하고, 최근 변환을 TLB(변환 색인 버퍼)에 캐싱해 매번 페이지 테이블을 뒤지는 비용을 줄인다. 이 구조 덕분에 프로세스 간 메모리 격리, 물리 메모리보다 큰 주소 공간, 요구 페이징(demand paging)이 가능해진다.
내부 구성
핵심 포인트
- 메모리 계층: 레지스터→L1→L2→L3(공유)→RAM→SSD→HDD, 위로 갈수록 빠르고 비싸고 작음
- 지역성(temporal/spatial locality)을 이용해 상위 캐시가 하위 계층 접근을 은폐, 평균 접근 시간 단축
- 프로세스 가상 메모리: Text→Data→BSS→Heap(↑)→mmap→Stack(↓) 순으로 배치
- Heap은 낮은 주소에서 위로, Stack은 높은 주소에서 아래로 성장 — 가운데 빈 공간을 두고 서로를 향해 자람
- BSS는 0으로 초기화되는 전역/정적 변수 영역으로, 실행 파일에는 크기 정보만 담겨 용량을 절약
- 사용자 영역(user space)/커널 영역(kernel space)을 분리해 커널 메모리를 보호
- MMU가 페이지 테이블로 가상→물리 주소를 변환하고, TLB가 최근 변환을 캐싱해 속도를 확보
심화
메모리 파트에서 가장 자주 빠지고, 면접에서 가장 자주 물어보는 것이 '스택과 힙의 성장 방향'과 'BSS가 왜 따로 존재하는가'다. 스택은 높은 주소에서 아래로, 힙은 낮은 주소에서 위로 성장하며 그 사이의 넓은 빈 공간이 두 영역이 런타임에 자유롭게 확장될 여지를 준다. 스택 오버플로(무한 재귀)나 힙과 스택의 충돌이 왜 발생하는지가 여기서 설명된다. BSS는 0으로 초기화되는 변수들을 위한 영역인데, 이 값들을 실행 파일에 일일이 저장하면 낭비이므로 '크기만' 기록해 두었다가 로더가 로드 시 0으로 채운다 — 그래서 큰 전역 배열을 선언해도 바이너리 크기가 커지지 않는다. Data는 0이 아닌 초기값이 있어 파일에 실제 값이 저장된다는 점에서 BSS와 대비된다. 가상 메모리의 핵심 가치는 격리(isolation)·추상화·초과 커밋(overcommit)이다. 각 프로세스가 동일한 가상 주소 0x400000에서 시작하는 것처럼 보여도 MMU가 서로 다른 물리 프레임으로 매핑하므로 프로세스 간 메모리가 완전히 분리되고, 잘못된 포인터가 다른 프로세스를 건드릴 수 없다. 여기서 반드시 알아야 할 성능 포인트가 TLB다. 페이지 테이블은 보통 4단계(x86-64)로, TLB 미스가 나면 최대 4번의 메모리 접근(page table walk)이 필요해 매우 느리다. 그래서 최근 변환을 TLB에 캐싱하고, 컨텍스트 스위칭 시 TLB 플러시 비용을 줄이려 ASID/PCID를 쓰며, 큰 메모리를 다루는 DB·JVM은 huge page(2MB/1GB)로 TLB 커버리지를 늘려 미스를 줄인다. 또한 요구 페이징(demand paging)과 페이지 폴트(page fault) — 접근한 페이지가 물리 메모리에 없을 때 MMU가 예외를 일으키고 OS가 디스크에서 페이지를 올리는 — 메커니즘까지 연결해 설명하면, '물리 메모리보다 큰 프로그램이 어떻게 실행되는가'라는 질문에 완결적으로 답할 수 있다.
쉽게 말하면 책상 위(캐시)에 자주 보는 책을 두고, 서재(RAM)까지 가는 횟수를 줄이는 것.