write-around
캐시에 없는 주소로 간 쓰기를 캐시에 채우지 않고 원본으로 곧장 보내는 결정입니다. 이미 캐시에 있는 주소에 쓰는 경우는 다른 전략이 맡습니다. 캐시를 채우는 일은 읽기에 맡깁니다. 그래서 방금 쓴 값을 읽으려면 원본까지 다녀와야 합니다.
쉽고 빠른 이해
한 번 쓰고 다시 안 읽을 데이터로 캐시를 밀어내지 않으려고, 캐시에 없는 주소로 간 쓰기를 캐시에 넣지 않고 원본으로 곧장 보냅니다. 백업이나 큰 파일 복사가 그런 쓰기입니다.
이렇게 안 하면 캐시가 쓰기 수요를 따라 채워집니다. 읽힐 값이 밀려 나갑니다.
- 쓰기가 캐시를 지나쳐 원본으로 갑니다. 캐시는 그 주소를 채우지 않습니다.
- 캐시가 채워지는 계기는 읽기 미스만 남습니다.
- 방금 쓴 값을 읽으면 미스가 나고, 그때 원본에서 올라옵니다.
대가는 그 한 번의 미스입니다. 곧 읽을 값을 쓴 작업 부하에서는 읽기가 원본까지 다녀옵니다.
상세
캐시에 쓰기가 들어올 때 정할 것이 하나 있습니다. 그 쓰기가 가리키는 주소가 캐시에 없을 때, 그 주소를 캐시에 실을지 말지입니다. 이것을 쓰기 미스 정책이라 부릅니다. write-around 는 그 둘 가운데 안 싣는 쪽입니다.
위키피디아의 Cache (computing) 문서가 이 갈림을 세워 둡니다. 쓰기 연산은 데이터를 돌려주지
않습니다. 그래서 쓰기 미스에서 결정이 하나 필요해집니다. 그 데이터를 캐시에 실을 것인가입니다.
싣는 쪽이 write allocate 이고, 안 싣는 쪽이 no-write allocate 입니다. 안 싣는 쪽은
write-no-allocate 또는 write around 라고도 부릅니다. 이 사전의 표제어 write-around 가 그 이름들과
같은 것입니다. 미스가 난 쓰기 위치의 데이터는 캐시에 실리지 않고 원본에 곧장 쓰입니다. 그리고 이
방식에서 데이터는 읽기 미스에서만 캐시에 실립니다.
flowchart TD
A["쓰기 도착"] --> B{"그 주소가 캐시에 있나"}
B -->|있음| C["적중 · write-through · write-behind 소관"]
B -->|없음| D{"그 주소를 캐시에 실을까"}
D -->|실음| E["write allocate"]
D -->|안 실음| F["write-around · 원본에 곧장 쓴다"]
F --> G["채워지는 계기는 읽기 미스만 남는다"]
첫 갈림이 이 표제어의 경계입니다. 쓰기가 캐시에 이미 있는 주소로 가면 그것은 적중이고, 쓰기 미스
정책이 다루는 대목이 아닙니다. 캐시와 원본에 함께 쓰는 write-through, 캐시에 먼저 쓰고 원본에는
나중에 반영하는 write-behind 가 그 쓰기를 맡습니다. 위키피디아와 커널 문서는 뒤엣것을 write-back
또는 writeback 이라 부릅니다. 셋은 같은 것을 가리키고, 이 사전의 표제어는 write-behind 입니다.
두 번째 갈림이 이 결정입니다. 캐시에 안 싣기로 하면 캐시가 채워지는 계기가 하나로 줄어듭니다. 읽기 미스입니다. 쓰기는 캐시의 내용을 늘리지 않습니다.
한 번 쓰고 다시 읽지 않을 데이터가 그런 쓰기입니다. 커널의 bcache 문서는 백업과 큰 파일 복사를 캐시를 전부 우회해야 하는 것으로 듭니다.
sequenceDiagram
autonumber
participant 앱
participant 캐시
participant 원본
앱->>원본: 쓰기 · 캐시를 지나친다
원본-->>앱: 완료
Note over 캐시: 그 주소는 비어 있다
앱->>캐시: 나중에 같은 주소를 읽는다
캐시-->>앱: 미스
캐시->>원본: 그 주소를 읽어 온다
원본-->>캐시: 값이 캐시에 실린다
쓰기와 읽기가 서로 다른 때에 일어납니다. 쓰기 때 캐시는 그 주소를 모릅니다. 읽기 때 비로소 그 주소가 캐시에 들어옵니다. 그 사이가 이 결정이 만드는 간격입니다.
여기까지는 이 이름을 쓰기 미스 정책으로 정의하는 쪽의 말입니다. 그래서 캐시에 남은 옛 값을 어떻게 하느냐가 답 없이 남는 것은 아닙니다. 쓰기 정책이 답합니다. 블록 계층 제품이 같은 이름을 더 넓은 범위에 쓰는 대목은 「이견」에서 따로 봅니다.
대가
얻는 것
- 한 번 쓰고 다시 안 읽을 데이터가 캐시에 있던 값을 밀어내지 않습니다. 10기가바이트 파일을 복사할 때 그 복사가 무작위로 접근되던 10기가바이트를 캐시에서 밀어내는 것은 아마 바라지 않을 일입니다. 백업과 큰 파일 복사가 그런 쓰기입니다.
- 캐시의 내용이 읽기 수요만 따라갑니다. 캐시가 채워지는 계기가 읽기 미스 하나로 줄어들기 때문입니다. 쓰기는 캐시의 내용을 늘리지 않습니다.
내주는 것
- write allocate 가 기대하던 이득을 접습니다. write-back 캐시는 대개 write allocate 를 씁니다. 같은 위치로 뒤이어 오는 쓰기나 읽기가 그 데이터를 캐시에 이미 가지고 있는 것에서 이득을 본다고 기대하기 때문입니다. write-around 에서 방금 쓴 주소는 캐시에 없습니다.
- 방금 쓴 주소를 곧 읽는 작업 부하에서는 읽기 미스가 한 번 더 생깁니다. 그 미스는 원본까지 다녀옵니다.
- 짝이 무엇인지에 따라 그 손실의 크기가 달라집니다. write-through 캐시는 no-write allocate 를 씁니다. 뒤이은 쓰기에는 이득이 없다는 것이 그 이유입니다. 그 쓰기도 결국 원본에 곧장 써야 하기 때문입니다.
예시
bcache 의 cache_mode
/sys/block/<bdev>/bcache/cache_mode
블록 계층 캐시 bcache 는 원본 장치마다 sysfs 파일로 모드를 내놓습니다. sysfs 는 리눅스 커널이
장치 설정을 파일처럼 보여 주는 가상 파일 시스템입니다. 커널 문서는 이 파일들이
/sys/block/<bdev>/bcache 와 /sys/block/bcache*/bcache 에 있다고 적습니다. 캐시 집합에 붙어
있으면 /sys/fs/bcache/<cset-uuid>/bdev* 에도 있습니다. cache_mode 가 가질 수 있는 값은
writethrough · writeback · writearound · none 넷입니다. 이 이름이 제품 설정 어휘로 굳은
대목입니다. 관리자가 장치마다 고르는 값입니다.
bcache 의 순차 입출력 자동 우회
# echo 0 > /sys/block/bcache0/bcache/sequential_cutoff
# echo 4m > /sys/block/bcache0/bcache/sequential_cutoff
같은 제품에 성격이 다른 우회가 하나 더 있습니다. 앞의 것은 장치마다 고르는 모드입니다. 이것은
요청마다 기계가 고르는 우회입니다. 커널 문서는 bcache 가 순차 입출력을 감지해 건너뛴다고
적습니다. 작업마다 입출력 크기의 이동 평균을 유지합니다. 그 평균이 문턱을 넘는 동안 그 작업의
모든 입출력을 건너뜁니다. 탐색마다 앞 512k 를 캐시하는 동작을 그 건너뜀으로 대신합니다. 그
문턱을 정하는 파일이 sequential_cutoff 입니다. 위 두 줄은 커널 문서에 적힌 것입니다. 앞 줄은
우회를 끄고, 뒷줄은 기본값 4m 으로 되돌립니다.
애플리케이션 캐시 제품 문서에서 이 이름을 쓰는 예시는 찾지 못했습니다(미확인).
경계
dm-cache 의 passthrough 도 write-around 인가. 아닙니다.
리눅스 커널의 장치 매퍼 캐시 dm-cache 에는 passthrough 라는 동작 모드가 있습니다. 커널 문서는 passthrough 를 고르면 모든 읽기가 원본 장치에서 처리되고 모든 쓰기가 원본 장치로 넘어간다고 적습니다. 모든 읽기가 캐시 미스가 된다고 괄호로 덧붙입니다. 쓰기가 캐시를 지나친다는 점은 write-around 와 같습니다.
가르는 선은 읽기입니다.
| write-around | passthrough | |
|---|---|---|
| 쓰기 | 캐시를 지나쳐 원본으로 | 캐시를 지나쳐 원본 장치로 |
| 읽기 | 캐시에서 처리 | 원본 장치에서 처리 |
| 캐시가 채워지는 계기 | 읽기 미스 | 없음 |
write-around 에서 읽기는 캐시에서 처리되고, 미스가 나면 그 값이 캐시에 올라옵니다. passthrough 에서는 읽기까지 원본으로 갑니다. 캐시가 채워지는 계기가 아예 없습니다. 그래서 passthrough 는 쓰기 미스 정책이 아니라 캐시를 쓰지 않는 모드입니다. 커널 문서가 붙이는 조건도 그것을 뒷받침합니다. passthrough 모드를 켜려면 캐시가 깨끗해야 합니다.
블록 계층에서 옛 값을 다루는 방식은 두 모드가 각각 적혀 있습니다. passthrough 에서는 쓰기 적중이 캐시 블록 무효화를 일으킨다고 커널 문서가 적습니다. bcache 쪽에서는 캐시를 우회하는 쓰기에 대해 그 주소의 캐시 데이터를 무효화한다고 적혀 있습니다. 쓰기 오류 처리 대목에서 괄호로 밝힌 것입니다. 둘 다 블록 계층 제품의 동작입니다.
이견
이 이름을 어느 층위의 선택으로 두는지가 문서마다 갈립니다.
위키피디아의 Cache (computing) 문서는 이것을 쓰기 미스 정책으로 둡니다. 짝은 write allocate
입니다. 그리고 캐시에 쓴 것을 언제 원본으로 보내는지 정하는 쓰기 정책을 별개의 축으로 세웁니다.
두 쓰기 정책이 어느 쓰기 미스 정책과도 맞물릴 수 있지만 대개 이렇게 짝지어진다고 그 문서는
적습니다.
| 쓰기 정책 | 대개 짝지어지는 쓰기 미스 정책 |
|---|---|
| write-back | write allocate |
| write-through | no-write allocate |
두 축이 직교한다는 말이 그 문장입니다.
커널의 bcache 문서는 다르게 둡니다. writearound 가 cache_mode 라는 한 설정 키의 값입니다.
writethrough · writeback · none 과 나란합니다. 위키피디아가 별개의 축으로 세운 것들이 한 키
안에서 서로 배타적인 선택지가 됩니다.
층위만 다른 것이 아닙니다. 이 이름이 걸리는 쓰기의 범위도 갈립니다. 쓰기 미스 정책으로 정의하는
쪽은 쓰기 미스에만 걸립니다. 캐시에 이미 있는 주소로 간 쓰기는 그 정의의 바깥이고 쓰기 정책이
받습니다. 커널의 bcache 문서 쪽은 그 경계를 그렇게 두지 않습니다. 캐시를 우회하는 쓰기에 대해 그
주소의 캐시 데이터를 무효화한다고 적혀 있습니다. 무효화할 데이터가 있다는 것은 그 주소가 캐시에
있었다는 뜻입니다. 그러므로 블록 계층의 우회는 캐시에 있는 주소로 간 쓰기에도 걸립니다. 다만
cache_mode 를 writearound 로 둔 원본 장치에서 모든 쓰기가 예외 없이 캐시를 우회하는지는 그
대목만으로 확인되지 않습니다(미확인).
어느 쪽이 이 이름의 본래 뜻인지를 두 문서 중 어느 쪽도 상대를 두고 적지 않았습니다.
관련 항목
이것과 맞세워지는 쓰기 미스 정책
write allocate · fetch on write · 쓰기 미스 · 캐시 미스 · write policy
같은 캐시에서 나란히 고르는 쓰기·읽기 전략
write-through · write-behind · cache-aside · read-through · refresh-ahead
이 이름을 설정값으로 싣는 블록 계층 캐시
bcache · dm-cache · passthrough · sysfs · 블록 장치
우회한 쓰기가 캐시에 남긴 값을 다루는 처리
무효화 · 낡은 데이터 · 캐시 일관성 · 축출 · dirty
이 결정이 기대는 캐싱 기본 개념
다른 이름: write around · writearound · no-write allocate · write-no-allocate