요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
mq, smq, cleaner
cache-policies.rst:25-131기본 smq의 memory 절감·level balancing·workload 적응, cleaner와 dmsetup 사용법을 설명합니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
=============================
Guidance for writing policies
=============================
Try to keep transactionality out of it. The core is careful to
avoid asking about anything that is migrating. This is a pain, but
makes it easier to write the policies.
Mappings are loaded into the policy at construction time.
Every bio that is mapped by the target is referred to the policy.
The policy can return a simple HIT or MISS or issue a migration.
Currently there's no way for the policy to issue background work,
e.g. to start writing back dirty blocks that are going to be evicted
soon.
Because we map bios, rather than requests it's easy for the policy
to get fooled by many small bios. For this reason the core target
issues periodic ticks to the policy. It's suggested that the policy
doesn't update states (eg, hit counts) for a block more than once
for each tick. The core ticks by watching bios complete, and so
trying to see when the io scheduler has let the ios run.
Overview of supplied cache replacement policies
===============================================
multiqueue (mq)
---------------
This policy is now an alias for smq (see below).
The following tunables are accepted, but have no effect::
'sequential_threshold <#nr_sequential_ios>'
'random_threshold <#nr_random_ios>'
'read_promote_adjustment <value>'
'write_promote_adjustment <value>'
'discard_promote_adjustment <value>'
Stochastic multiqueue (smq)
---------------------------
This policy is the default.
The stochastic multi-queue (smq) policy addresses some of the problems
with the multiqueue (mq) policy.
The smq policy (vs mq) offers the promise of less memory utilization,
improved performance and increased adaptability in the face of changing
workloads. smq also does not have any cumbersome tuning knobs.
Users may switch from "mq" to "smq" simply by appropriately reloading a
DM table that is using the cache target. Doing so will cause all of the
mq policy's hints to be dropped. Also, performance of the cache may
degrade slightly until smq recalculates the origin device's hotspots
that should be cached.
Memory usage
^^^^^^^^^^^^
The mq policy used a lot of memory; 88 bytes per cache block on a 64
bit machine.
smq uses 28bit indexes to implement its data structures rather than
pointers. It avoids storing an explicit hit count for each block. It
has a 'hotspot' queue, rather than a pre-cache, which uses a quarter of
the entries (each hotspot block covers a larger area than a single
cache block).
All this means smq uses ~25bytes per cache block. Still a lot of
memory, but a substantial improvement nonetheless.
Level balancing
^^^^^^^^^^^^^^^
mq placed entries in different levels of the multiqueue structures
based on their hit count (~ln(hit count)). This meant the bottom
levels generally had the most entries, and the top ones had very
few. Having unbalanced levels like this reduced the efficacy of the
multiqueue.
smq does not maintain a hit count, instead it swaps hit entries with
the least recently used entry from the level above. The overall
ordering being a side effect of this stochastic process. With this
scheme we can decide how many entries occupy each multiqueue level,
resulting in better promotion/demotion decisions.
Adaptability:
The mq policy maintained a hit count for each cache block. For a
different block to get promoted to the cache its hit count has to
exceed the lowest currently in the cache. This meant it could take a
long time for the cache to adapt between varying IO patterns.
smq doesn't maintain hit counts, so a lot of this problem just goes
away. In addition it tracks performance of the hotspot queue, which
is used to decide which blocks to promote. If the hotspot queue is
performing badly then it starts moving entries more quickly between
levels. This lets it adapt to new IO patterns very quickly.
Performance
^^^^^^^^^^^
Testing smq shows substantially better performance than mq.
cleaner
-------
The cleaner writes back all dirty blocks in a cache to decommission it.
Examples
========
The syntax for a table is::
cache <metadata dev> <cache dev> <origin dev> <block size>
<#feature_args> [<feature arg>]*
<policy> <#policy_args> [<policy arg>]*
The syntax to send a message using the dmsetup command is::
dmsetup message <mapped device> 0 sequential_threshold 1024
dmsetup message <mapped device> 0 random_threshold 8
Using dmsetup::
dmsetup create blah --table "0 268435456 cache /dev/sdb /dev/sdc \
/dev/sdd 512 0 mq 4 sequential_threshold 1024 random_threshold 8"
creates a 128GB large mapped device named 'blah' with the
sequential threshold set to 1024 and the random_threshold set to 8.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
정책 모듈이 지켜야 할 계약
1-24정책 구현에는 transaction 처리를 넣지 않는 편이 좋습니다. Core는 migration 중인 항목에 관해 정책에 묻지 않도록 주의합니다. Core 쪽 처리는 번거로워지지만 policy를 작성하기는 쉬워집니다.
기존 mapping은 policy를 생성할 때 policy 안으로 load됩니다. Target이 map하는 모든 bio는 policy에 전달되며, policy는 단순한 `HIT` 또는 `MISS`를 반환하거나 migration을 요청할 수 있습니다.
현재 policy가 background work를 직접 시작할 방법은 없습니다. 예를 들어 곧 evict할 dirty block을 미리 writeback하도록 요청할 수 없습니다.
Request가 아니라 bio를 map하므로 작은 bio가 많이 들어오면 policy가 실제 중요도를 잘못 판단하기 쉽습니다. 이를 완화하려고 core target은 policy에 주기적인 tick을 보냅니다. Block의 hit count 같은 상태는 tick마다 한 번보다 자주 갱신하지 않는 것이 권장됩니다. Core는 bio completion을 관찰해 tick을 만들며, 이를 통해 I/O scheduler가 실제 I/O를 실행하도록 내보낸 시점을 가늠합니다.
Core가 migration 중 항목을 제외하고 bio 관찰과 주기적 tick을 policy에 전달하는 흐름입니다.
multiqueue(mq) 호환 alias
25-41제공되는 cache replacement policy 가운데 `multiqueue`(`mq`)는 이제 아래의 `smq`를 가리키는 alias입니다.
다음 tunable은 호환성을 위해 받아들이지만 실제 동작에는 아무 영향도 주지 않습니다.
The following tunables are accepted, but have no effect::
'sequential_threshold <#nr_sequential_ios>'
'random_threshold <#nr_random_ios>'
'read_promote_adjustment <value>'
'write_promote_adjustment <value>'
'discard_promote_adjustment <value>'
Parameter는 parse되지만 현재 mq alias의 동작을 바꾸지 않습니다.
기본 stochastic multiqueue 정책
42-59`stochastic multiqueue`(`smq`)가 기본 policy입니다. 기존 `mq`의 여러 문제를 해결하며, 더 적은 memory 사용량, 향상된 performance, 바뀌는 workload에 대한 높은 적응성을 목표로 합니다. 번거로운 tuning knob도 없습니다.
Cache target을 사용하는 DM table을 적절히 reload하면 `mq`에서 `smq`로 전환할 수 있습니다. 이때 mq policy hint는 모두 버려집니다. smq가 origin device에서 cache할 hotspot을 다시 계산할 때까지 cache performance가 잠시 조금 낮아질 수 있습니다.
DM table reload 뒤 기존 hint를 버리고 hotspot을 다시 학습합니다.
smq memory 사용량
60-7464-bit machine에서 mq policy는 cache block 하나당 88 byte를 사용해 memory 소비가 컸습니다.
smq는 pointer 대신 28-bit index로 data structure를 구현하고 block마다 명시적인 hit count를 저장하지 않습니다. Pre-cache 대신 `hotspot` queue를 두며, 이 queue는 전체 entry의 4분의 1만 사용합니다. 각 hotspot block은 cache block 하나보다 더 넓은 영역을 대표합니다.
이 변화로 smq는 cache block당 약 25 byte를 사용합니다. 여전히 적지 않지만 mq보다 크게 개선된 수치입니다.
smq는 index와 압축된 hotspot 표현으로 block당 overhead를 줄입니다.
Level balancing과 workload 적응
75-106mq는 hit count의 대략적인 자연로그 값에 따라 entry를 multiqueue level에 배치했습니다. 그래서 아래 level에는 entry가 많고 위 level에는 거의 없는 불균형이 생겼고, multiqueue의 효율이 낮아졌습니다.
smq는 hit count를 유지하지 않습니다. Hit된 entry를 바로 위 level의 least-recently-used entry와 교환하고, 이 stochastic process의 부수 효과로 전체 순서를 만듭니다. 따라서 각 level이 차지할 entry 수를 정할 수 있고 promotion과 demotion 결정을 더 잘 내릴 수 있습니다.
mq에서는 새 block의 hit count가 현재 cache에 있는 가장 낮은 hit count보다 커져야 promotion될 수 있어 I/O pattern 변화에 적응하는 데 오래 걸렸습니다. smq는 hit count를 없애 이 문제 대부분을 피합니다.
smq는 promotion 대상 결정에 쓰는 hotspot queue의 성능도 추적합니다. Hotspot queue의 성능이 나쁘면 level 사이에서 entry를 더 빠르게 옮겨 새 I/O pattern에 빠르게 적응합니다. 시험 결과 smq는 mq보다 상당히 나은 performance를 보였습니다.
명시적 hit counter 대신 인접 level의 LRU entry와 교환해 순서와 균형을 함께 만듭니다.
cleaner와 dmsetup 사용 예
107-131`cleaner` policy는 cache를 폐기할 수 있도록 cache의 dirty block을 모두 origin으로 writeback합니다.
Cache target table은 metadata device, cache device, origin device, block size, feature argument, policy와 policy argument를 다음 순서로 받습니다.
cache <metadata dev> <cache dev> <origin dev> <block size>
<#feature_args> [<feature arg>]*
<policy> <#policy_args> [<policy arg>]*
`dmsetup message`로 mapped device의 policy tunable을 바꾸는 형식과 예는 다음과 같습니다.
dmsetup message <mapped device> 0 sequential_threshold 1024
dmsetup message <mapped device> 0 random_threshold 8
아래 명령은 `blah`라는 128GB mapped device를 만들고 sequential threshold를 1024, `random_threshold`를 8로 지정합니다. 다만 현재 `mq`는 `smq` alias이므로 앞서 설명한 tunable은 받아들이기만 하고 효과는 없습니다.
dmsetup create blah --table "0 268435456 cache /dev/sdb /dev/sdc \
/dev/sdd 512 0 mq 4 sequential_threshold 1024 random_threshold 8"
creates a 128GB large mapped device named 'blah' with the
sequential threshold set to 1024 and the random_threshold set to 8.
Cleaner는 dirty data를 정리하고 dmsetup table/message는 policy와 parameter를 지정합니다.
Policy core 계약
cache-policies.rst:1-24Bio별 policy 호출, migration exclusion과 tick당 상태 갱신 규칙을 정리합니다.