Cache eviction · interactive guide

S3-FIFO:
用三條 FIFO,挑出真正值得留下的資料

不在每次命中時搬動資料;先用小佇列快速篩掉一次性流量,再讓真正被重複使用的物件進入主快取。

SimpleScalable3 Static FIFO queues
開始操作動畫 ↓
The cache problem

快取最怕的,是「只來一次」的訪客。

容量有限時,新資料持續湧入。若它們大多只讀一次,卻和熱門資料一樣佔著位置,快取命中率就會被稀釋。這類資料常被稱為 one-hit wonders

AXYAZA
S3-FIFO 的核心提問:新資料是否值得立刻進入主快取? 先給它一個短暫、成本低的觀察期。

傳統 FIFO

最早放入者先淘汰;結構簡單,但不分物件是否已經被再次使用。

LRU

每次命中都要把物件移到最新端。效果常佳,但高併發下會引入共享 metadata 的更新與競爭。

S3-FIFO

命中只增加一個小型存取計數;佇列位置不動。淘汰時才根據計數決定去留。

Hands-on simulation

用同一串請求,親眼看出差異。

請求序列刻意混入短命的 X、Y、Z、E、F;A 和 B 則會再出現。選擇演算法後按「下一步」,或讓它自動播放。此為教學用的小容量模型,突出策略差異。

FIFO:先進先出

容量 4;每次命中不改變佇列。
命中:0未命中:0目前步驟:0 / 10
How S3-FIFO thinks

不是三層階級,而是三種不同的責任。

新請求
Small S
快速試用區
Main M
長期主快取
Ghost G
只留近期淘汰的 key
再次請求
跳過 S,直接進 M

新物件先放進 Small(S)

S 約使用快取容量的一小部分(研究中的常見起點是 10%)。物件初始頻率計數為 0。

S 滿時,快速篩選

輪到 S 最舊物件離開時,未曾再次被讀到的物件進 Ghost(G);被讀過的物件才晉升到 Main(M),並清除其計數。

Main(M)用 FIFO-Reinsertion 守住熱門物件

M 的最舊物件若有被存取過,就重新放回 M 尾端,並把 2-bit 計數遞減;若沒有再被使用,才真正淘汰。

Ghost(G)讓「差一點就成功」的物件有第二次機會

G 不存 value,只存近期從 S 淘汰的 metadata。若同一 key 很快又被請求,直接進 M,而不必再從 S 慢慢證明自己。

Decision matrix

FIFO、LRU、S3-FIFO:該在意什麼?

面向原始 FIFOLRUS3-FIFO
命中時的佇列操作不移動移到最新端不移動;只遞增有上限的計數
對一次性資料無特別防護可能把它暫時保到前面S 快速篩選
高併發可擴展性命中時 metadata 更新易成熱點;熱門命中不需調整佇列
熱門資料的保護以最近使用時間保護以「是否累積再使用」保護,M 可重插入
額外 metadata通常需 linked-list 指標低;2-bit 存取狀態 + Ghost key/指紋
適合的直覺場景極簡、可預期的淘汰重視近期性且寫入競爭可接受掃描/一次性資料多,又需要吞吐量
Engineering notes

落地時,記住這幾個細節。

容量應以 bytes 衡量

真實快取的物件大小不一,S 與 M 的上限通常以佔用 bytes 而不是物件數計算。G 只保留 metadata,不占資料快取的 value 容量。


計數要有上限

論文的設計用兩個 access bits(等價於最高 3)。飽和後的熱門命中不必再寫 metadata,可降低競爭。


佇列最好是 O(1) ring buffer

FIFO 不需要在命中時抽出再插回,因此可以避免 LRU 鏈結串列在多執行緒下頻繁更新同一份結構。

// 概念化的請求處理(非 production code)
if key 在 M 或 S:
  accessBits[key] = min(accessBits[key] + 1, 3)

else if key 在 Ghost G:
  從 G 的紀錄復活 value
  插入 Main M // 已證明它不是單次訪客

else:
  插入 Small S,accessBits = 0

S 需要騰空時:
  if 最舊物件的 accessBits > 0:移至 M
  else:移至 Ghost G

M 需要騰空時:
  if 最舊物件的 accessBits > 0:
    accessBits--;重新插入 M 尾端
  else:真正淘汰