vatt'ghern jaskier's ballads
本文 1 個互動圖表在手機上以重點摘要呈現,互動版請以桌面瀏覽器開啟。

Agent 暫停幾分鐘去跑一個工具、等一次人工核准,回頭送出下一輪請求時,帳單卻像是從頭問了一次——Anthropic 的量測顯示,十分鐘閒置之後,四十八次測試裡沒有一次快取還活著。

KV cache 保溫的帳:keepalive 的成本經濟學

分鐘,是這篇調查裡反覆出現的一個數字。多輪 agent 的典型節奏是送一個請求、觸發一次工具呼叫或等一次人工核准、再把結果接回去問下一輪——這中間的空檔從幾秒到幾分鐘不等。provider 賣的故事很簡單:只要下一輪的 prompt 跟上一輪共享同一段前綴,你就付大約一成的輸入價、還跳過大部分 prefill 延遲。問題是這個折扣是設計給「很快就會再問一次」的場景,agent 工作流恰好踩在最容易犯規的地方——中間的空檔剛好長到讓快取被清掉。一篇新發表的 arXiv 論文《Keeping the Cache Warm Pays: Keepalive Economics for Agentic Workloads》想把「定期戳一下、別讓快取死掉」這件事算清楚:多久戳一次最划算、閒置要多長才值得戳、戳這件事本身又要付多少錢。同一天,作者 Maxim Khailo 另外寫了一篇部落格,實測跨 Anthropic、OpenAI、Gemini、DeepSeek 四家量測快取到底撐得住多久——兩份材料出自同一人、同一批底層資料,一份是量測敘事,一份是把數字套進成本模型,合起來看才看得出完整的帳,不能當成兩方互證的獨立結果。論文原文特別點出這個空檔的量級是「幾分鐘」,不是幾秒——這正好是後面十分鐘閒置測試點會落在懸崖之後的原因:agent 等一次核准的時間,往往就比五分鐘的 TTL 還長。

這次的量測不是隨手起幾次 curl 就下結論。mempko 用的是一個能自證時間戳的 harness,對 Anthropic、OpenAI、Gemini、DeepSeek 四家分別送出間隔遞增的請求,測兩種前綴大小、多個閒置時間點,每個配置都獨立跑三輪,不是單次量測就寫進結論。能自證時間戳這件事本身就是方法論的重點——量測快取存活與否,最怕的就是本機時鐘跟伺服器端時鐘對不上,讓「閒置了幾分鐘」這個關鍵變數本身就失真,harness 特別把這一步做成可驗證的,量出來的懸崖與黏性形狀才站得住腳。前面提到的「四十八個樣本」,就是這三輪測試在同一個閒置點上加總出來的分母;Google 的樣本數明顯薄很多,論文自己承認每格只有三到七個,看那條偏黏的線時要多打一個折扣,不能跟樣本數更厚的 Anthropic、OpenAI 放在同一個信心水準上比較。論文與部落格是同一天出的:arXiv 論文的提交時間是協調世界時 7 月 21 日下午 3 點 45 分,部落格同日發布,兩者共用同一批底層量測資料。

暫停十分鐘,快取說掉就掉

論文摘要把問題講得很直白:provider 快取一段 prompt 處理過的前綴,讓分享同一段前綴的後續請求只付大約一成輸入價、還省掉大部分 prefill 延遲;但 agentic workload 會系統性地把這個好處吃掉——agent 送出請求、跑一個工具或等一次核准,等到下一輪真的送出時,快取的前綴早就被逐出,agent 只能重新付一次全額 prefill。這不是個案,是這套折扣設計原本就沒算到的用法。mempko 的部落格把這句話量成數字:Anthropic 在完全不做任何保溫動作的基準情況下,五分鐘內快取還活著,但撐到十分鐘時,三輪測試、四十八個樣本,全部逐出。不是「大部分掉了」,是乾脆俐落的懸崖——五分鐘還在,十分鐘全滅。

切換命中/逐出兩種路徑 · 同一段前綴的兩種下場

同一段前綴,兩種下場 request response cache 已逐出 · 全額 prefill
命中時這段前綴幾乎是直線通過,只付大約輸入價的一成;逐出之後同一段前綴要整段重新算過,畫成一條起伏更大的路徑——曲線形狀是示意,「約一成」與「全額 prefill」兩個數字來自論文摘要對這套折扣機制的描述。

懸崖、黏性、漏水——逐出不是一個時間常數

如果把「快取多久會死」想成放諸四海皆準的一個數字,那就錯了。同一套測試方法量出四種完全不同的形狀。Anthropic 是硬懸崖:五分鐘的 TTL 一到,不管你在懸崖前一秒還是後一秒送出下一輪,結果就是全有或全無——這也是為什麼它的基準行為在五分鐘與十分鐘之間切得這麼乾淨。OpenAI 相反,測試裡不開 keepalive、閒置十分鐘,四十八個樣本仍有三十九個命中,行為更接近「多半撐得住,但會有零星漏網」的機率性存活,不是明確的時間牆。Google/Gemini 走同一條路線,二十四個樣本裡二十個仍然命中,同樣偏黏。DeepSeek 是第四種、也最麻煩:基準測試裡它在每一個測試間隔都在漏,不是撐到某個時間點才整批消失,十分鐘時四十八個樣本只剩四個還熱著。作者還觀察到一個額外的複雜因素——DeepSeek 經過 DeepInfra 路由,保溫的 ping 可能熱了一台後端機器,緊接著的真實請求卻被分派到另一台機器,等於白 ping。這不是快取演算法的問題,是路由層把保溫這件事變得不確定。硬懸崖與機率性黏並不只是說法上的差別,是工程判斷完全不同:面對 Anthropic 這種懸崖,只要抓準 TTL 就能穩定命中或穩定重算,行為可預測;面對 OpenAI、Google 這種黏,同樣的閒置長度下,這次命中下次未必命中,要嘛接受偶爾的全額 prefill,要嘛乾脆假設它一定會逐出去設計重試邏輯。

拖動閒置秒數,看 Anthropic 的 5 分鐘 TTL 懸崖 · 0-600 秒

WARM · 約 10% 輸入價 EVICTED · 全額 prefill 5 min · TTL 0 10 min

idle 600 秒(10 分鐘)→ 已逐出,這次全額 prefill

Anthropic 沒有開 keepalive 的基準行為:閒置在 5 分鐘 TTL 之前都還命中,過了 TTL 就是硬性全滅——三輪測試共 48 個樣本,10 分鐘時無一命中。拖動圓點可以檢視 0 到 10 分鐘之間任意時刻的狀態。

上面這些逐出形狀,講的都是完全不做保溫動作的基準行為。反過來問,keepalive 這個手段本身有沒有效?論文給的答案很乾脆——「在我們測過的每個地方都有效」:四家 provider、兩種前綴大小、所有閒置時長組合起來,開了 keepalive 之後的快取命中率中位數維持在 98% 以上,某些條件下甚至能把暫停後那一次請求的成本壓到冷啟動的十二分之一。這個十二倍是效果的上限,出現在特定 provider、特定閒置長度的組合裡,不是每次保溫都能拿到,但作為量級參考,已經足夠說明這不是聊勝於無的小優化。把這個數字放回前面的懸崖圖來看,反差更明顯——Anthropic 完全不保溫十分鐘後是 0/48 命中,一旦開了 keepalive,命中率中位數卻能拉到 98% 以上,說明真正決定生死的不是快取機制本身撐不撐得住,而是有沒有人定期去戳它。換句話說,「保溫有沒有用」從來不是懸念,它幾乎每次都有用;真正要算的,是下一節的問題:這筆保溫的錢,划不划算。

那就每三十秒戳一次?

逐出行為摸清楚之後,直覺的下一步是:定期送一個小請求把快取戳醒,不要讓它閒到觸發逐出。網路上流傳的慣例是每三十秒戳一次。問題是這個頻率本身要付錢——每次戳都是一次 cached-read,累加起來不是免費的。論文算過一個具體例子:用三十秒頻率保溫一個十萬 token 的 Anthropic 前綴,一小時要付大約 3.6 美元。mempko 的量測把這個問題釘死在一個更直接的數字上:三十秒慣例的損益兩平點大約落在六分鐘,一旦閒置超過六分鐘,這個頻率在四家 provider 上全部倒賠——不是省得少,是淨虧損,因為戳的成本已經超過放著不管、下一輪重新 prefill 的成本。

論文把這筆帳寫成一個很直接的比較:每戳一次要付一次 cached-read 價 r(Anthropic 大約是輸入價的一成),不戳的話,下一輪送出時就要付一次全額 re-prefill 價 w;把 ping 間隔 τ 與閒置時長 I 代進去,keepalive 划不划算的臨界點——論文稱作損益兩平閒置時長——寫成 I_max=τ(w/r−1)。這個公式不是拿來背,是拿來反推:先量出自己的 agent 在工具呼叫或人工核准之間,典型會閒置多久,再看這個時長有沒有超過門檻;沒超過,keepalive 連頻率都不用選,直接不開最省。拿 Anthropic 的數字代進去看更具體:r 大約是輸入價的一成、w 是全額輸入價,τ* 抓在四分鐘附近,算出來的損益兩平閒置時長落在四十六分鐘——這就是為什麼十分鐘的測試閒置對 Anthropic 來說連門檻的四分之一都不到,keepalive 在那個位置理所當然是划算的。

點任一家 provider 看三種情境的實際帳單 · 4 家 provider

Anthropic 0 / 48 基準存活 keepalive 省 38% OpenAI 39 / 48 基準存活 keepalive 賠錢 DeepSeek 4 / 48 基準存活 賠錢·快 3× Gemini 20 / 24 基準存活 keepalive 賠 40% Anthropic Sonnet 4.5 · 100k 前綴 · 10 分鐘閒置:冷啟動 $0.667 → 30 秒 keepalive $0.867(貴)→ 約 4 分鐘 keepalive $0.414(省 38%)
四家 provider 在同一個 10 分鐘閒置、10 萬 token 前綴的測試點上:左半是不開 keepalive 的基準存活率,右半是「用論文建議頻率保溫」對比冷啟動的成本判定。點任一行看三種情境(冷啟動/30 秒/約 4 分鐘)的完整帳單。

把頻率貼著 TTL 邊緣,划算嗎?

論文給的修正很簡單:別每三十秒戳一次,改成貼著 TTL 邊緣、留一點餘裕再戳。以 Anthropic 五分鐘的 TTL 為例,論文算出來的經濟頻率大約是四分鐘一次,論文原話說三十秒慣例「比真正需要的頻率多花八倍」——上一節那組 3.6 美元對 0.45 美元,就是三十秒與四分鐘這兩個頻率保溫同一個前綴一小時的實際差距。但「頻率調對了」不等於「每家都值得開」。前面那張並排表已經看得出來:同一個十分鐘閒置點上,只有 Anthropic 一家,四分鐘頻率的帳單比冷啟動便宜,作者原話是「在這個間隔上,只有 Anthropic 做 keepalive 是省錢的」。DeepSeek 雖然也賠錢,但換到明顯更快的回應——冷啟動要等 5.4 秒才開始吐字,保溫之後降到 1.4 到 2.0 秒,快了將近三倍,對延遲敏感的場景這筆帳未必只能用美元算。論文自己算出的損益兩平閒置時長解釋了這個落差:Anthropic 約四十六分鐘,OpenAI 與 DeepSeek 約三十六分鐘,Google 只有大約十二分鐘——十分鐘的測試閒置離 Anthropic 的門檻還很遠,卻已經逼近或超過其他三家的門檻,keepalive 在那個位置本來就該虧。換句話說,Google 的 keepalive 幾乎在所有 agent 的典型閒置場景裡都不會回本,除非閒置長度真的長到逼近或超過十二分鐘還持續保溫,否則保溫的錢基本上是浪費的。

損益兩平閒置時長(論文模型算出,分鐘) Anthropic 46 分 OpenAI 36 分 DeepSeek 36 分 Google 12 分 測試閒置 10 分鐘
四條門檻線是論文用成本模型算出來的「閒置要撐多久,keepalive 才開始比重新 prefill 划算」,不是額外量到的數字。虛線標出前面兩個小節共用的 10 分鐘測試點——離 Anthropic 的門檻還遠,卻已經越過 Google 的門檻,等於 Google 在這個閒置長度上必然是淨虧損。

把 ping 間隔拉長本身有一個連續的成本曲線,值得直接看數字怎麼隨頻率變化——同一個十萬 token 的 Anthropic 前綴,戳得越勤,每小時的保溫帳單越高,但曲線在接近 TTL 邊緣之前就已經壓得很平,不需要真的貼到懸崖邊也能拿到大半的省錢空間。

拖動 ping 間隔 τ,看每小時保溫成本怎麼變 · 30-280 秒

240 秒 → $0.45/hr
ping 間隔 τ(秒) 每小時成本(美元) $0 $1 $2 $3 TTL 300s 30 秒慣例 · $3.60/hr τ* · $0.45/hr
曲線公式 (I/τ+1)×r,套進論文給的兩個錨點(30 秒 $3.60/hr、τ*≈240 秒 $0.45/hr)反推常數畫出,兩點在數字上剛好差 8 倍。曲線在 τ 拉到約 150 秒之後已經很平,繼續逼近 TTL 邊緣的邊際省下並不大。

所有人都戳,快取層會發生什麼事?

上面的演算法都假設你是快取層裡唯一一個在戳的人。論文在後段把這個假設拿掉,問了一個更麻煩的問題:如果每個 agent 都學會了這套划算的策略,同時對同一個快取層開 keepalive,會發生什麼事?論文用一句話總結這個處境:個體理性、集體卻在自打嘴巴。單一 agent 把自己的前綴定期戳醒是理性選擇,帳算得過去;但快取層的容量是所有租戶共用的,如果每個租戶都把自己的條目釘住不放,provider 原本用來決定「淘汰誰」的 LRU 演算法就沒有真正冷的條目可以排序——論文的說法是,LRU 沒有東西可以排名,這一層會退化成先到先佔。換句話說,keepalive 一旦普及,它解決的問題(避免被逐出)會反過來製造它自己的稀缺:大家都在保溫,能被淘汰讓出空間的條目變少,真正需要新空間的冷啟動請求反而更難搶到位置。論文對這個外部性的推測是,它會推著 provider 從「照次計費的 cached-read 折扣」轉向「照 token-hour 計費」的模式,並指出 Google 的 explicit context cache 已經走在這條路上。這部分是論文對未來走向的推測,不是已經量到的結果,但邏輯站得住:只要保溫的成本低於重新 prefill,個別 agent 就沒有理由不開,provider 要嘛忍受這個外部性,要嘛把計費模型改成不怕被保溫策略套利。退化成先到先佔對使用者最直接的影響是:原本「閒置最久的內容最先被踢」這種可預期的行為會消失,變成「誰先佔住位置誰就贏」,這種不確定性本身也是一種隱藏成本,只是還沒被算進上面任何一張帳單裡。如果真的走到 token-hour 計費那一步,對讀者的影響也很直接:現在的心算公式(每次 ping 一次 cached-read 價)會整個作廢,因為計費單位從「你戳了幾次」變成「你佔住了多久」,屆時保溫划不划算要重新算一次,不是套用今天這篇論文裡的常數。

mempko 把整篇實測濃縮成一句建議——「保溫,但要短、要對頻率、少戳」。放進均衡問題裡看,這句話有雙重意思:對單一 agent 是省錢的訣竅,對整層共用的快取則是降低集體外部性的辦法——愈少不必要的 ping,愈多真正冷的條目能被 LRU 正常排序、正常淘汰。

拖動採用率、play 看保溫佔用如何擠壓可用容量 · 24 格快取

60%
24 格代表一個共用 cache tier 的容量。橘色格是被某個 agent 用 keepalive 釘住的條目(脈動代表定期 ping),綠色格是仍可被 LRU 自由淘汰、讓給新的冷啟動請求的空間。這是根據論文對均衡問題的敘述畫的示意,格數與脈動節奏是說明用的示意值,不是論文量到的具體數字。

24 格代表一個共用 cache tier 的容量

當多數 agent 都對同一塊 cache 開 keepalive,能被淘汰的冷條目變少,共用的快取容量被瓜分,退化成先到先佔。

把這些數字串起來,讀者的判斷順序其實很機械:先量出自己的 agent 在工具呼叫或人工核准之間,典型的閒置時長落在哪個區間;再對照要用的 provider 各自的損益兩平閒置時長——Anthropic 約 46 分鐘、OpenAI 與 DeepSeek 約 36 分鐘、Google 只有大約 12 分鐘。閒置沒摸到這個數字,keepalive 就是淨支出,讓快取自然死掉、下一輪重新 prefill 反而比較省;真的要開,頻率要貼著各家 TTL 邊緣算,不是抄網路上流傳的 30 秒慣例。如果系統本身是多 provider 路由,這個判斷還得對每一家分開做一次——mempko 的量測結論很直接:同一個 10 分鐘閒置點上,keepalive 只有在 Anthropic 一家上真的省錢,把同一組參數原封不動套到另外三家,只會白花錢。這個判斷程序背後的假設是:同一套 keepalive 參數沒辦法通用,因為每家 provider 的逐出形狀(懸崖、黏、漏水)本來就不是同一種機制,套用同一個頻率,等於拿懸崖的邏輯去套一個本來就黏的系統。把 30 秒慣例套進任何一個閒置超過 6 分鐘的 agent 迴圈,就是在複製 mempko 那組 3.6 美元對 0.45 美元的差距——只是很少有人把這筆帳單真的攤開來看。

Take-away:不要把 30 秒 keepalive 當成安全預設去抄——先確認你的典型閒置時長有沒有摸到損益兩平點,再決定要不要開、開多快;沒摸到門檻,放著讓快取自然死掉,反而比較省。