頁大小(page size)
想像用桶子搬沙。小茶杯在最後一杯杯口幾乎不浪費沙,但你得跑上一千趟、還要記一大本哪一杯放到哪。一個巨型大桶一趟搞定、帳本極薄,但你若只有一小把沙,大桶大半是空的——浪費了。頁大小就是記憶體那只桶子的大小,而選它正是這個取捨:小頁浪費少,卻需要龐大的記帳;大頁記帳輕,卻在最後那不滿的一頁浪費更多。
具體而言,頁大小是一頁與一個頁框裡固定的位元組數,永遠是 2 的次方(常見為 4 KB;也有 2 MB 或 1 GB 的「大頁」)。這個大小決定邏輯位址如何切分:2^n 位元組的頁,意味著 n 個位元的偏移,其餘作為頁號。把頁做得「較小」有兩個效果:「內部」碎裂較少,因為最後一頁浪費的尾巴至多是一頁減一位元組(故平均約半個小頁);但分頁表有「更多」項目(要對應給定的位址空間需要更多頁),而項目數固定的 TLB 涵蓋的「總記憶體變少」,於是失誤更頻繁。把頁做得「較大」則兩者反轉:表的負擔較少,每筆 TLB 項目涵蓋的記憶體大得多(對大工作集極好),但內部碎裂更多,且保護、共享,以及(在虛擬記憶體中)磁碟傳輸的粒度變粗。
頁大小之所以重要,是因為它是一個沒有白吃午餐的真實調校旋鈕:沒有唯一最佳值,只有適合該工作負載的平衡。現代系統常同時支援一個小的預設頁加上選用的大頁,讓擁有龐大、密集工作集的資料庫或科學程式用大頁來大砍 TLB 失誤,而一般程式維持小頁以限制浪費。常見的誤解是以為大頁就是單純地「比較快」——它們確實減輕 TLB 壓力,但會因內部碎裂浪費更多記憶體,並使細粒度的共享與分頁更笨拙,所以正確的大小確實要看程式在做什麼。
某程式碰觸散布在許多頁上的 4 MB 資料。用 4 KB 頁時它橫跨 1024 頁,遠超過 64 筆項目的 TLB 所能涵蓋,於是不斷失誤。改用 2 MB 大頁,同樣的 4 MB 只需 2 頁——兩頁都能輕鬆塞進 TLB,消除失誤,代價是若最後一個大頁幾乎沒用到,可能浪費將近 2 MB。
較大的頁讓每筆 TLB 項目涵蓋更多記憶體(失誤更少),卻在最後不滿的一頁浪費更多——一個貨真價實的取捨。
大頁並非單純地「比較快」:它們減少 TLB 失誤與表的負擔,卻提高內部碎裂、並使共享與保護變粗。沒有放諸四海皆準的最佳頁大小,只有適合某工作負載的正確平衡。