Odborný článok

Ukladanie podmnožín fontov na disk s HotPDF v Delphi

HotPDF dokáže udržiavať podmnožiny TrueType a OpenType fontov na disku a znova ich použiť naprieč dokumentmi a naprieč spusteniami procesu, takže dávka, ktorá renderuje desaťtisíc výpisov s tými istými troma fontmi, vytvorí podmnožiny týchto fontov raz namiesto desaťtisíckrát. Vyrovnávacia pamäť sa konfiguruje dvoma vlastnosťami, skúma sa jedným záznamom a je bezpečné ju nechať zapnutú: zlyhanie vyrovnávacej pamäte spadne späť na bežné subsetovanie v pamäti a nikdy nezastaví produkciu dokumentu

Subsetovanie je drahé z konkrétneho dôvodu. Stavba podmnožiny znamená prejsť uzáver glyphov, prepísať loca a glyf, prestavať cmap a hmtx a vyprodukovať CID mapovanie, ktoré môže PDF adresovať. Pre jeden dokument sa táto cena stratí v šume. Pre reportovací server produkujúci dokumenty v slučke je to často najväčší jeden blok CPU času v běhu

Čo umožňuje zásah do vyrovnávacej pamäte

Štyri veci sa musia zhodovať: obsah fontu, množina použitých glyphov, režim subsetovania a schéma vyrovnávacej pamäte. Ak sa nesúhlasí čokoľvek, HotPDF subsetuje od začiatku, pretože podmnožina je opakovane použiteľná iba vtedy, keď by bola aj tak byte-identická

Množina glyphov je podmienka, ktorá ľudí prekvapí. Dve faktúry, ktoré sa líšia jedným menom zákazníka, používajú odlišné množiny glyphov, a preto produkujú odlišné podmnožiny a odlišné záznamy vo vyrovnávacej pamäti. Vyrovnávacia pamäť sa vyplatí, keď dokumenty zdieľajú repertoár glyphov — výpisy z pevnej šablóny, formuláre, ktorých premenné dáta sú číselné, katalógy čerpané z jednej produktovej databázy — a neprináša nič, keď každý dokument kreslí iný výsek z veľkého CJK rezu. Predpokladajte, v ktorom prípade ste, až po meraní

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;

Ako viete, že vyrovnávacia pamäť niečo robí?

GetFontSubsetCacheInfo vracia deväť počítadiel a pomer medzi prvými dvoma odpovedá na otázku priamo. HitCount a MissCount dávajú hit rate. WriteCount a EvictionCount ukazujú, či záznamy prežijú dostatočne dlho na opätovné použitie, alebo ich vytláča rozpočet, ktorý je príliš malý. CurrentBytes a FileCount hlásia, čo je na disku práve teraz

Zostávajúce tri sú tie, na ktoré sa oplatí nastaviť alert. CorruptCount počíta záznamy, ktoré zlyhali pri validácii a boli odstránené — niekoľko po nečistom vypnutí je normálnych, stabilný prúd znamená, že úložisko je nespoľahlivé. RejectedCount počíta záznamy odmietnuté pred použitím. WriteFailureCount počíta záznamy, ktoré sa vôbec nedali zapísať, čo zvyčajne znamená problém s oprávneniami na priečinok a nie niečo o fontoch. Žiadne z týchto troch nezastaví generovanie dokumentu, čo je presne dôvod, prečo sa na ne musíte pozrieť: vyrovnávacia pamäť, ktorá potichu nikdy nezapisuje, zvonka vyzerá rovnako ako vyrovnávacia pamäť, ktorá funguje, s výnimkou účtu za CPU

Evikcia, rozpočty a okamih, keď jeden zoženiete

FontSubsetCacheMaxBytes má predvolenú hodnotu 268435456 bajtov, to je 256 MiB, a dá sa znížiť za behu. Zníženie spustí okamžitú evikciu najmenej nedávno použitých namiesto čakania na ďalší zápis, takže služba reagujúca na tlak na disku dokáže uvoľniť miesto v okamihu, kedy sa pre to rozhodne, a nie v niektorom neskoršom, ktorý neovláda

Nastavenie FontSubsetCacheFolder na prázdny reťazec vypne diskovú vrstvu bez vyčistenia už uložených položiek a bez zmeny jediného bajtu fontového výstupu. To je vlastnosť, po ktorej siahnete, keď chcete vyrovnávaciu pamäť izolovať počas riešenia problémov: vypnite ju, spustite rovnakú dávku a porovnajte vyprodukované PDF. Mali by byť identické, pretože vyrovnávacia pamäť ukladá výsledok a nie politiku

Čo urobí vyrovnávacia pamäť, keď je záznam poškodený

Odstráni ho a subsetuje normálne. Poškodené alebo skrátené záznamy sú odmietnuté skôr, než by podmnožina mohla dôjsť do PDF streamu, čo je časť návrhu, na ktorej najviac záleží: poškodený záznam vyrovnávacej pamäte, ktorý by sa dostal do dokumentu, by vyprodukoval PDF s poškodeným fontovým programom a to zlyhanie by sa prejavilo ďaleko od svojej príčiny — v prehliadači, na stroji zákazníka, o týždne neskôr

Zápisy sú atomické, takže čitateľ nikdy nepozoruje napoly zapísaný záznam a pád v polovici zápisu zanechá vyrovnávaciu pamäť konzistentnú namiesto otrávenú. Kompaktné záznamy podmnožín si zachovávajú dáta CID remapovania, ktoré fontové slovníky PDF/A vyžadujú, takže uložená podmnožina je stále zhodná podmnožinou — archivačný výstup nemusí obísť vyrovnávaciu pamäť, aby zostal platný

// 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');

Kam umiestniť priečinok v reálnom nasadení

Tri vlastnosti to rozhodujú: priečinok musí byť zapisovateľný účtom, pod ktorým beží služba, mal by byť na lokálnom úložisku a nie na sieťovom zdieľaní, a nemal by byť vnútri adresára, ktorý krok nasadenia vymaže. Vyrovnávacia pamäť na zdieľaní zmení každý miss na okružnú cestu a každý zásah na dve; vyrovnávacia pamäť pod aplikačným adresárom, ktorý inštalátor znovu vytvorí, je vyrovnávacia pamäť, ktorá začína od nuly po každej aktualizácii

Pre služby s viacerými inštanciami dajte každej inštancii jej vlastný priečinok, pokiaľ ste nepotvrdili, že úložisko zvláda súbežnú atomickú náhradu tak, ako očakávate. Cena duplikovaného záznamu je jeden extra prechod subsetovania; cena debugovania preteku na zdieľanej vyrovnávacej pamäti je jedno popoludnie

Kedy siahnuť po niečom inom

Vyrovnávacia pamäť redukuje opakovanú prácu. Neredukuje prácu prvého dokumentu a nepomáha workloadu, ktorého množiny glyphov sa nikdy neopakujú. Ak váš výstup dominuje jeden obrovský CJK rez použitý naprieč nepredvídateľným textom, efektívnejšia páka je samotný uzáver subsetovania — ktoré glyphy sa pritiahli a prečo — čo pokrývajú poznámky k uzáveru podmnožín fontov a tvarovaniu glyphov. Ak je vaša dávka pomalá z dôvodov, ktoré sa ukážu byť vôbec nie fonty, návod k reportovému výstupu s fontmi a obrázkami ukazuje, kde zvyčajne odíde zvyšný čas, a prípadová štúdia bugu poradia subsetovania fontov v EndDoc je pripomienkou, že správnosť subsetovania a rýchlosť subsetovania sú rozdielne problémy

HotPDF je natívny VCL PDF komponent pre Delphi a C++Builder a vyrovnávacia pamäť podmnožín je súčasťou knižnice a nie doplnkovou službou, takže ju reportovací server získa nastavením jednej cesty k priečinku — kompletný zoznam fontových a výkonnostných funkcií nájdete na stránke HotPDF komponentu