缓存基础结构
HotPDF 为可复用的中间对象提供有界的加权内存缓存,并为已加载文档的渲染提供持久化的已渲染页面缓存
加权内存缓存
THPDFWeightedCache(位于 HPDFCache)持有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 个独立加锁的元数据分片协调已加载图像的解码复用
- 缓存查找与准入只持有选中的分片锁,昂贵的过滤器与图像解码在缓存锁外运行
- 按键精确的 singleflight 选出一个 owner 解码,重复调用方等待同一完成结果
- 配置的
ImageCacheMaxBytes、条目数上限与单条目上限在所有分片间保持全局 - 解码图像条目持有不可变的引用计数句柄,可在驱逐后存活,让渲染器热命中时无需物化
TBitmap拷贝 - 完成的图像拷贝进调用方持有的
TBitmap实例,调用方无法改动保留的缓存像素 - 文档重载与图像缓存失效会清除已完成条目,活动 flight 对象保留自己的引用计数生命周期
GetImageDecodeConcurrencyInfo报告活动飞行、活动与峰值 owner 解码、等待、完成与失败
ICC 变换缓存
HPDFICC 经线程安全的 64 MiB 加权 LRU 缓存共享完整的 source 到 sRGB 变换,配置时含 proof 与输出 profile
- SHA-256 键覆盖完整的源、proof 与输出 profile 内容、生效的渲染意图与黑点补偿设置
HPDFGetICCTransformCacheInfo报告命中、未命中、驱逐、拒绝、条目数、当前字节与最大字节HPDFSetICCTransformCacheMaxBytes立即应用新的进程级预算,并按需驱逐最久未用的变换HPDFClearICCTransformCache释放保留的变换并重置请求统计,不使调用方已持有的变换接口失效
持久化字体子集缓存
设置 THotPDF.FontSubsetCacheFolder 以在 EnableFontSubsetting 激活时启用可复用的 TrueType 与 OpenType 子集结果
- 键覆盖原始字体字节、精确的已用字形位图、紧凑或稀疏模式以及缓存模式版本
- 常规 GDI 字体库路径与已注册 Unicode 字体终结器复用同一缓存
- 紧凑 PDF/A 条目保留
CIDToGIDMap - 条目使用前校验,损坏条目被移除,替换使用原子的同目录移动
FontSubsetCacheMaxBytes立即生效,驱逐最久未访问的精确缓存文件,不遍历无关文件夹GetFontSubsetCacheInfo报告命中、未命中、写入、驱逐、损坏、拒绝、写失败、字节与文件数ClearFontSubsetCache只从配置的文件夹移除字体子集条目与被弃置的临时条目
PDF.EnableFontSubsetting := True;
PDF.FontSubsetCacheFolder := 'C:\ProgramData\MyApp\HotPDF\FontSubsets';
PDF.FontSubsetCacheMaxBytes := 256 * 1024 * 1024;已加载字体的解码器缓存
设置 THotPDF.RenderCacheFolder 以启用内存已渲染页面缓存之后的磁盘层
- 页面文件按键包含文档内容、从 0 开始的页面索引、DPI、生效的可选内容可见性、颜色意图与回退策略
- 图层与颜色意图变化选择可复用的状态变体,而不是丢弃所有缓存位图
- PNG 与索引更新是原子的,弃置的临时文件在恢复期间移除
- 页面读取刷新页面级新近度;文档数、页面数与字节上限驱逐最久未用数据
- 调低配置上限立即收敛,而不是等待后续写入
- 损坏的 PNG 文件、过期或重复的索引行、缺失的文件夹以及未索引的缓存文件夹会自动修复
- 无效的文档键和坐标会在文件系统访问之前被拒绝
- 恢复、读取、写入、失效和驱逐期间会跳过以链接形式存在的文档文件夹;链接及其外部目标文件保持原样
所有权
THPDFWeightedCache拥有传递给Put的对象,除非所有权经Extract转移THPDFDiskPageCache.Lookup返回由调用方拥有的新分配位图- 传递给
THPDFDiskPageCache.Store的位图值仍由调用方拥有