Технічна стаття

Кешування підмножин шрифтів на диску з HotPDF у Delphi

HotPDF здатен зберігати підмножини шрифтів TrueType та OpenType на диску й повторно використовувати їх між документами та запусками процесу, тож партія, що рендерить десять тисяч виписок з тими самими трьома шрифтами, будує ці підмножини один раз, а не десять тисяч разів. Кеш налаштовується двома властивостями, перевіряється одним записом і безпечний для залишання увімкненим: збій кешу відкочувається до звичайного підмноження в пам'яті й ніколи не зупиняє створення документа

Підмноження дороге з причини. Побудова підмножини означає обхід замикання гліфів, переписування loca та glyf, перебудову cmap та hmtx і випуск відображення CID, яке PDF може адресувати. Для одного документа ця ціна губиться в шумі. Для сервера звітів, що породжує документи в циклі, це часто найбільший єдиний блок процесорного часу в запуску

Що робить влучення в кеш можливим

Мають збігатися чотири речі: вміст шрифта, набір використаних гліфів, режим підмножини та схема кешу. Промах у будь-якій — і HotPDF будує підмножину з нуля, бо підмножина повторно використовується лише тоді, коли вона все одно була б побайтно ідентичною

Набір гліфів — це та умова, що дивує людей. Два рахунки, які різняться одним іменем клієнта, використовують різні набори гліфів, тож дають різні підмножини та різні записи в кеші. Кеш окупляється, коли документи поділяють гліфовий репертуар — виписки з фіксованого шаблона, форми з числовими змінними, каталоги з однієї бази продуктів — і нічого не дає, коли кожен документ малює інший зріз великої CJK-гарнітури. Виміряйте, перш ніж припускати, у якому випадку ви

var
  Pdf: THotPDF;
  Info: THPDFFontSubsetCacheInfo;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.EnableFontSubsetting := True;
    Pdf.FontSubsetCacheFolder := 'C:\ProgramData\Reports\fontcache';
    Pdf.FontSubsetCacheMaxBytes := 64 * 1024 * 1024;   // 64 MiB, default is 256
    // ... generate the batch ...
    Info := Pdf.GetFontSubsetCacheInfo;
    LogFmt('subset cache: %d hits, %d misses, %d bytes in %d files',
      [Info.HitCount, Info.MissCount, Info.CurrentBytes, Info.FileCount]);
  finally
    Pdf.Free;
  end;
end;

Звідки знаєте, що кеш узагалі щось робить?

GetFontSubsetCacheInfo повертає дев'ять лічильників, і співвідношення між першими двома відповідає на запитання прямо. HitCount та MissCount дають частоту влучень. WriteCount та EvictionCount показують, чи записи живуть достатньо довго, щоб їх повторно використати, чи їх витісняє занадто малий бюджет. CurrentBytes та FileCount звітують, що на диску прямо зараз

Решта три — ті, на які варто стежити. CorruptCount рахує записи, що не пройшли валідацію та були видалені — кілька після брудного завершення нормальні, стабільний потік означає, що носій ненадійний. RejectedCount рахує записи, відмовлені до використання. WriteFailureCount рахує записи, які взагалі не вдалося записати, що зазвичай означає проблему з правами на папку, а не щось про шрифти. Жодна з цих трьох не зупиняє генерацію документів, і саме тому вам доводиться на них дивитися: кеш, що мовчки ніколи не пише, виглядає ззовні так само, як кеш, що працює, окрім рахунку за процесор

Витіснення, бюджети та момент, коли ви стискаєте один

FontSubsetCacheMaxBytes за замовчуванням дорівнює 268435456 байтів, тобто 256 MiB, і може бути зменшене під час виконання. Зменшення запускає негайне витіснення з найбільш давно використаного, а не чекає на наступний запис, тож служба, що реагує на тиск диска, може звільнити місце в момент, коли вона вирішує це зробити, а не в якийсь пізніший, який вона не контролює

Установлення FontSubsetCacheFolder у порожній рядок вимикає дисковий рівень, не очищаючи вже збереженого й не змінивши жодного байта шрифтового виводу. Це та властивість, якою користуються, коли хочете ізолювати кеш під час усунення несправностей: вимкніть, запустіть ту саму партію порівняно зі створеними PDF. Вони мають бути ідентичні, бо кеш зберігає результат, а не політику

Що робить кеш, коли запис пошкоджено

Видаляє його та будує підмножину як зазвичай. Деформовані або обрізані записи відхиляються до того, як підмножина може потрапити в потік PDF, і саме ця частина дизайну найважливіша: пошкоджений запис кешу, що дістався б у документ, породив би PDF із зламаною шрифтовою програмою, а ця відмова спливла б далеко від причини — у переглядачі, на машині клієнта, через кілька тижнів

Записи атомарні, тож читач ніколи не спостерігає напівзаписаний запис, а збій посеред запису залишає кеш узгодженим, а не отруєним. Компактні записи підмножин зберігають дані перенумерації CID, яких вимагають шрифтові словники PDF/A, тож кешована підмножина все ще відповідна підмножина — архівний вивід не змушений оминати кеш, щоб залишатися правомірним

// Reset the disk tier after a font upgrade or a schema change
Pdf.ClearFontSubsetCache;

// Or move it somewhere writable and let the budget apply immediately
Pdf.SetFontSubsetCacheFolder('D:\cache\fonts');

Куди покласти папку в реальному розгортанні

Це вирішують три властивості: папка має бути доступною для запису під обліковим записом, під яким працює служба; вона має знаходитись на локальному носії, а не в мережевій шеринзі; і вона не має бути в каталозі, який витирає крок розгортання. Кеш на шерингу перетворює кожен промах на кругову поїздку, а кожне влучення на дві; кеш під папкою застосунку, яку відтворює інсталятор, — це кеш, що стартує холодним після кожного оновлення

Для служб з кількома інстанціями дайте кожній інстанції власну папку, якщо ви не підтвердили, що носій обробляє паралельне атомарне заміщення так, як ви очікуєте. Ціна дубльованого запису — один додатковий прохід підмноження; ціна налагодження гонитви на спільному кеші — цілий післяобідній час

Коли звернутися до чогось іншого

Кеш зменшує повторну роботу. Він не зменшує роботу першого документа й не допомагає навантаженню, чиї набори гліфів ніколи не повторюються. Якщо ваш вивід домінує однією величезною CJK-гарнітурою, використаною на непередбачуваному тексті, ефективнішим важелем є саме замикання підмножини — які гліфи затягуються і чому, — описане в нотатках про замикання підмножин шрифтів та формування гліфів. Якщо ваша партія повільна з причин, що виявляються не у шрифтах взагалі, нарис виводу звітів зі шрифтами та зображеннями показує, куди зазвичай іде інший час, а тематичне дослідження вади впорядкування підмножини шрифтів у EndDoc нагадує, що коректність підмноження та швидкість підмноження — окремі проблеми

HotPDF — це рідний VCL-компонент PDF для Delphi та C++Builder, а кеш підмножин є частиною бібліотеки, а не службою-надбудовою, тож сервер звітів отримує його встановленням одного шляху до папки — дивіться сторінку компонента HotPDF щодо повного списку шрифтових та продуктивних можливостей