HotPDF kan behålla TrueType- och OpenType-teckensnittsdelmängder på disk och återanvända dem över dokument och processkörningar, så en batch som renderar tiotusen kontoutdrag med samma tre teckensnitt delmängdskapar de teckensnitten en gång i stället för tiotusen gånger. Cachen konfigureras med två egenskaper, inspekteras med en post och är säker att lämna på: ett cachefel faller tillbaka på normal minnesbunden delmängdskapande och stoppar aldrig ett dokument från att produceras
Delmängdskapande är dyrt av en anledning. Att bygga en delmängd betyder att gå igenom glyfslutet, skriva om loca och glyf, bygga om cmap och hmtx, och emittera en CID-mappning PDF:en kan adressera. För ett dokument försvinner den kostnaden in i bruset. För en rapportserver som producerar dokument i en loop är det ofta det största enskilda blocket av CPU-tid i körningen
Vad som möjliggör en cache-träff
Fyra saker måste stämma: teckensnittsinnehållet, mängden av använda glyfer, delmängdsläget och cacheschemat. Missa någon av dem så delmängdskapar HotPDF från grunden, eftersom en delmängd bara är återanvändbar när den ändå skulle ha varit byte-identisk
Glyfmängden är det villkor som överraskar folk. Två fakturor som skiljer sig åt med ett enda kundnamn använder olika glyfmängder och producerar därför olika delmängder och olika cacheposter. Cachen lönar sig när dokument delar ett glyfrepertoar — kontoutdrag från en fast mall, formulär vars variabla data är numerisk, kataloger dragna från en produktdatabas — och lönar ingenting när varje dokument drar en annan skiva av ett stort CJK-typsnitt. Mät innan du antar vilket fall du befinner dig i
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;
Hur vet du att cachar gör någonting?
GetFontSubsetCacheInfo returnerar nio räknare, och förhållandet mellan de två första besvarar frågan direkt. HitCount och MissCount ger träffrekten. WriteCount och EvictionCount visar huruvida poster överlever tillräckligt länge för att återanvändas eller håller på att trängas ut av en budget som är för liten. CurrentBytes och FileCount rapporterar vad som finns på disk just nu
De återstående tre är de som är värda att varna på. CorruptCount räknar poster som misslyckades validering och togs bort — några efter en oren nedstängning är normala, en stadig ström betyder att lagringen är otillförlitlig. RejectedCount räknar poster vägrade innan användning. WriteFailureCount räknar poster som inte kunde skrivas alls, vilket vanligtvis betyder ett behörighetsproblem på mappen i stället för någonting om teckensnitt. Ingen av dessa tre stoppar dokumentgenerering, vilket är exakt varför du måste titta på dem: en cache som tyst aldrig skriver ser likadan ut utifrån som en cache som fungerar, förutom CPU-räkningen
Utstötning budgetar och ögonblicket du krymper en
FontSubsetCacheMaxBytes är som standard 268435456 byte, det vill säga 256 MiB, och det kan sänkas vid körning. Att sänka det utlöser omedelbar minst-nyligen-använd-utstötning i stället för att vänta på nästa skrivning, så en tjänst som reagerar på disktryck kan frigöra utrymme i det ögonblick den beslutar sig för det, inte vid någon senare punkt den inte kontrollerar
Att sätta FontSubsetCacheFolder till en tom sträng inaktiverar disknivån utan att rensa någonting redan lagrat och utan att ändra en enda byte av teckensnittsutdata. Det är den egenskap du sträcker dig efter när du vill isolera cachen vid felsökning: stäng av den, kör samma batch och jämför de producerade PDF:erna. De bör vara identiska, eftersom cachen lagrar ett resultat, inte en policy
Vad cachen gör när en post är skadad
Den tar bort den och delmängdskapar normalt. Missformade eller trunkerade poster förkastas innan delmängden kan nå en PDF-ström, vilket är den del av designen som betyder mest: en korrumperad cachepost som tog sig in i ett dokument skulle producera en PDF med ett trasigt teckensnittsprogram, och det felet skulle ytra sig långt från sin orsak — i en visare, på en kunds maskin, veckor senare
Skrivningar är atomära, så en läsare observerar aldrig en halvskriven post, och en krasch mitt i en skrivning lämnar cachen konsistent i stället för förgiftad. Kompakta delmängdsposter behåller CID-ommappningsdatan som PDF/A-teckensnittsordböcker kräver, så en cachad delmängd är fortfarande en överensstämmande delmängd — arkivutdata behöver inte kringgå cachen för att förbli giltig
// 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');
Var du ska placera mappen i en verklig distribution
Tre egenskaper avgör detta: mappen måste vara skrivbar av det konto som tjänsten körs som, den bör sitta på lokal lagring i stället för på en nätverksdelning, och den bör inte ligga inuti en katalog som ett distributionssteg rensar. En cache på en delning förvandlar varje miss till en rundtur och varje träff till två; en cache under en applikationsmapp som installatören återskapar är en cache som startar kall efter varje uppdatering
För tjänster med flera instanser, ge varje instans sin egen mapp om du inte har bekräftat att lagringen hanterar samtidig atomär ersättning som du förväntar dig. Kostnaden för en duplicerad post är en extra delmängdskaps-passage; kostnaden för att felsöka ett cachadelningsrace är en eftermiddag
När du ska sträcka dig efter något annat
Cachen minskar upprepat arbete. Den minskar inte arbetet för det första dokumentet, och den hjälper inte en arbetsbelastning vars glyfmängder aldrig upprepas. Om din utdata domineras av ett enormt CJK-typsnitt använt över oförutsägbart text är den mer effektiva spaken själva delmängdslutet — vilka glyfer som dras in, och varför — täckt i noterna om teckensnittsdelmängdslut och formande glyfer. Om din batch är långsam av skäl som visar sig inte vara teckensnitt alls, visar genomgången av rapportutdata med teckensnitt och bilder var den andra tiden vanligtvis går, och fallstudien om EndDoc-teckensnittsdelmängds-ordningsfelet är en påminnelse om att delmängdskapandets korrekthet och delmängdskapandets hastighet är separata problem
HotPDF är en inbyggd VCL PDF-komponent för Delphi och C++Builder, och delmängdscachen är del av biblioteket i stället för en tilläggstjänst, så en rapportserver får den genom att sätta en mappsökväg — se HotPDF-komponentsidan för hela teckensnitts- och prestandafunktionslistan