快取基礎結構
HotPDF 為可重複使用的 intermediary 物件提供有界的加權記憶體快取,並提供已載入文件轉譯所使用的持續性已轉譯頁面快取
加權記憶體快取
HPDFCache 中的 THPDFWeightedCache 擁有 TObject 值,以 AnsiString 為它們建立索引,並在合計權重符合 MaxBytes 之前持續收回最久未使用的值
Get與TryGet會將命中的項目提升為最近使用,並更新要求統計資料Peek與ContainsKey檢查項目時不會改變最近性或要求統計資料Put接管擁有權、就地取代現有索引鍵,且當只有權重變更時也能安全地再次接受同一個物件Remove會釋放項目,而Extract會將擁有權轉移給呼叫端- 減少
MaxBytes會立即收回項目,而TrimToBudget則明確公開相同的收斂作業 Hits、Misses、HitRate、Evictions、Rejections與Replacements公開快取行為,而ResetStatistics會開始新的量測區間- 插槽容量以等比方式增長,且作用中的項目會維持以常數時間的最近性順序連結
內容索引鍵
function HPDFCacheKeyOfBytes(const Bytes: TBytes): AnsiString;
function HPDFCacheKeyOfStream(Stream: TStream): AnsiString;
兩個函式對相同內容都會傳回相同的小寫 SHA-256 十六進位索引鍵
HPDFCacheKeyOfStream 在雜湊時不會配置第二個完整大小的位元組陣列,會從位置零讀取可搜尋的串流,並還原其原始位置
持續性已轉譯頁面快取
設定 THotPDF.RenderCacheFolder 即可啟用記憶體內已轉譯頁面快取之後所使用的磁碟層
- 頁面檔案以文件內容、從零開始的頁面索引與 DPI 做為索引鍵
- PNG 與索引更新都是不可部分完成的,且復原期間會移除被棄置的暫存檔案
- 頁面讀取會重新整理頁面層級的最近性,而文件數、頁面數與位元組限制則會收回最久未使用的資料
- 減少已設定的限制會立即收斂,而無須等待後續寫入
GetLoadedFontDecoder會深拷貝受管理的陣列,呼叫端因此無法改動快取的對應表或寬度 - 文件重新載入、物件圖變更、頁面失效、JSON Patch,以及每一次
CMapResourcePath指派,都會清除保留的解碼器 - 解碼器的取得在每份文件內序列化,避免同一字型重複解析,但該鎖定並不保證並行的文件變更安全
GetLoadedFontDecoderCacheInfo公開項目數、估計位元組、預算、命中、未命中、解析次數、驅逐與失效次數
分片式已載入影像解碼快取
每個 THotPDF 實例透過 16 個獨立鎖定的中繼資料分片,協調已載入影像的解碼重用
- 快取查詢與准入只持有選定的分片,昂貴的 filter 與影像解碼則在快取鎖定之外執行
- 每鍵精確的 singleflight 會選出唯一的擁有者解碼,重複的呼叫端等待同一份完成結果
- 設定的
ImageCacheMaxBytes、項目數上限與單項上限在所有分片間全域生效 - 解碼後的影像項目持有不可變的引用計數控制代碼,驅逐後仍存活,讓轉譯器畫出暖命中而不必具體化
TBitmap拷貝 - 完成的影像會拷貝到呼叫端持有的
TBitmap實例,呼叫端因此無法改動保留在快取中的像素 - 文件重新載入與影像快取失效會清除完成的項目,進行中的 flight 物件則保留自己的引用計數生命週期
GetImageDecodeConcurrencyInfo回報進行中的 flight、作用中與尖峰擁有者解碼、等待、完成與失敗次數
ICC 轉換快取
HPDFICC 透過 thread-safe 的 64 MiB 加權 LRU 快取共用完整的來源至 sRGB 轉換,設定時也包含 proof 與輸出 profile
- SHA-256 鍵涵蓋完整的來源、proof 與輸出 profile 內容,以及有效的 rendering intent 與黑點補償設定
HPDFGetICCTransformCacheInfo回報命中、未命中、驅逐、拒絕、項目數、目前位元組與最大位元組HPDFSetICCTransformCacheMaxBytes立即套用新的 process 層級預算,並視需要驅逐最久未用的轉換HPDFClearICCTransformCache釋放保留的轉換並重設請求統計,但不會讓呼叫端已持有的轉換介面失效
持續化的字型子集快取
設定 THotPDF.FontSubsetCacheFolder 即可在 EnableFontSubsetting 啟用時重用 TrueType 與 OpenType 子集結果
- 快取鍵涵蓋原始字型位元組、確切的已用 glyph 點陣、compact 或 sparse 模式,以及快取 schema 版本
- 一般 GDI 字型存放區路徑與註冊的 Unicode 字型 finalizer 共用同一個快取
- Compact PDF/A 項目保留
CIDToGIDMap所需的舊到新 GID 對應與新 glyph 數 - 項目使用前會先驗證,損毀的項目會被移除,替換時採用原子的同目錄搬移
FontSubsetCacheMaxBytes立即生效,只驅逐最久未存取的精確快取檔,不會走訪無關資料夾GetFontSubsetCacheInfo回報命中、未命中、寫入、驅逐、損毀、拒絕、寫入失敗、位元組與檔案數ClearFontSubsetCache只從設定的資料夾移除字型子集項目與被遺棄的暫存項目
PDF.EnableFontSubsetting := True;
PDF.FontSubsetCacheFolder := 'C:\ProgramData\MyApp\HotPDF\FontSubsets';
PDF.FontSubsetCacheMaxBytes := 256 * 1024 * 1024;
持續化的已轉譯頁面快取
設定 THotPDF.RenderCacheFolder 即可啟用記憶體內已轉譯頁面快取之後的磁碟層
- 頁面檔案的鍵由文件內容、零基頁索引、DPI、有效的可選內容可見性、色彩意圖與後備原則組成
- 圖層與色彩意圖變更會挑選可重用的狀態變體,而不是丟棄所有快取的點陣圖
- PNG 與索引更新皆為原子操作,復原期間會移除被遺棄的暫存檔
- 頁面讀取會更新頁面層級的近期度;文件數、頁數與位元組上限則驅逐最久未用的資料
- 調低設定上限會立即收斂,不必等待之後的寫入
- 毀損的 PNG 檔案、過時或重複的索引列、缺少的資料夾,以及未建立索引的快取資料夾都會自動修復
- 無效的文件索引鍵與座標會在存取檔案系統之前遭到拒絕
- 修復、讀取、寫入、失效與驅逐期間會跳過以連結方式掛入的文件資料夾;連結本身與其外部目標檔案都會保留
擁有權
THPDFWeightedCache擁有傳遞給Put的值,除非該值是由Extract傳回THPDFDiskPageCache.Lookup傳回由呼叫端擁有、新配置的點陣圖- 傳遞給
THPDFDiskPageCache.Store的點陣圖值仍由呼叫端擁有
相關 API
- THotPDF.RenderCacheFolder
- THotPDF.RenderCacheMaxDocuments
- THotPDF.RenderCacheMaxBytes
- THotPDF.RenderLoadedPageToBitmapCached
- THotPDF.GetImageDecodeConcurrencyInfo
- THotPDF.RenderCacheFolder
- THotPDF.RenderCacheMaxDocuments
- THotPDF.RenderCacheMaxBytes
- THotPDF.RenderLoadedPageToBitmapCached
- Rendering Diagnostics and Operation Telemetry