Teknisk artikkel

Mellomlagring av skriftdelmengder på disk med HotPDF i Delphi

HotPDF kan beholde TrueType- og OpenType-skriftdelmengder på disk og gjenbruke dem på tvers av dokumenter og på tvers av prosesskjøringer, slik at en gruppe som renderer ti tusen kontoutskrifter med de samme tre skriftene delmengder de skriftene én gang i stedet for ti tusen ganger. Mellomlageret konfigureres med to egenskaper, inspiseres med én post, og er trygt å la stå på: et mellomlager-svikt faller tilbake til vanlig delmengde-deling i minne og stopper aldri et dokument fra å bli produsert

Delmengde-deling er dyrt av en grunn. Å bygge en delmengde betyr å gå gjennom glyff-lukkingen, skrive om loca og glyf, bygge om cmap og hmtx, og sende ut en CID-tilordning PDF-en kan adressere. For ett dokument forsvinner den kostnaden i støyen. For en rapporttjener som produserer dokumenter i en løkke, er det ofte den største enkelblokken av CPU-tid i kjøringen

Hva som gjør et mellomlager-treff mulig

Fire ting må stemme: skriftinnholdet, mengden av brukte glyffer, delmengde-modusen, og mellomlager-skjemaet. Bom på én og HotPDF delmengder fra bunnen av, fordi en delmengde bare er gjenbrukbar når den ville vært byte-identisk uansett

Glyff-mengden er den betingelsen som overrasker folk. To fakturaer som skiller seg med ett enkelt kundenavn bruker ulike glyff-mengder, og produserer derfor ulike delmengder og ulike mellomlager-oppføringer. Mellomlageret betaler seg når dokumenter deler et glyff-repertoar — kontoutskrifter fra en fast mal, skjema hvis variable data er numeriske, kataloger trukket fra én produktdatabase — og betaler ingenting når hvert dokument tegner en ulik skive av en stor CJK-skrift. Mål før du antar hvilket tilfelle du er 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;

Hvordan vet du at mellomlageret gjør noe som helst?

GetFontSubsetCacheInfo returnerer ni tellere, og forholdet mellom de to første svarer på spørsmålet direkte. HitCount og MissCount gir treffraten. WriteCount og EvictionCount viser om oppføringer overlever lenge nok til å bli gjenbrukt eller blir dyttet ut av et budsjett som er for lite. CurrentBytes og FileCount rapporterer hva som ligger på disk akkurat nå

De resterende tre er de det lønner seg å varsle på. CorruptCount teller oppføringer som feilet validering og ble fjernet — noen få etter en uren nedstenging er normale, en jevn strøm betyr at lagringen er upålitelig. RejectedCount teller oppføringer nektet før bruk. WriteFailureCount teller oppføringer som ikke kunne skrives i det hele tatt, noe som vanligvis betyr et tillatelsesproblem på mappen snarere enn noe om skrifter. Ingen av disse tre stopper dokumentgenerering, noe som er akkurat grunnen til at du må se på dem: et mellomlager som i stillhet aldri skriver ser det samme ut fra utsiden som et mellomlager som virker, bortsett fra CPU-regningen

Utkasting, budsjetter og øyeblikket du krymper et

FontSubsetCacheMaxBytes er standardisert til 268435456 bytes, altså 256 MiB, og kan senkes ved kjøretid. Å senke den utløser umiddelbar minst-nylig-brukt-utkast i stedet for å vente på neste skriving, slik at en tjeneste som reagerer på disk-press kan frigjøre plass i det øyeblikket den bestemmer seg for det, ikke på et senere tidspunkt den ikke kontrollerer

Å sette FontSubsetCacheFolder til en tom streng deaktiverer disk-nivået uten å tømme noe som allerede er lagret, og uten å endre en eneste byte av skrift-utdata. Det er egenskapen du griper etter når du vil isolere mellomlageret under feilsøking: slå det av, kjør den samme gruppen, og sammenlikn de produserte PDF-ene. De bør være identiske, fordi mellomlageret lagrer et resultat, ikke en policy

Hva mellomlageret gjør når en oppføring er skadet

Den fjerner den og delmengder normalt. Feilformede eller avkortede oppføringer avvises før delmengden kan nå en PDF-strøm, noe som er den delen av designet som betyr mest: en korrupt mellomlager-oppføring som kom seg inn i et dokument ville produsert en PDF med et ødelagt skriftprogram, og det sviktet ville dukke opp langt fra sin årsak — i en leser, på en kundes maskin, uker senere

Skrivinger er atomære, slik at en leser aldri observerer en halvskrevet oppføring, og et krasj midt i en skriving etterlater mellomlageret konsistent snarere enn forgiftet. Kompakte delmengde-oppføringer beholder CID-omtilordningsdataene som PDF/A-skriftordbøker krever, slik at en mellomlagret delmengde fortsatt er en konform delmengde — arkivutdata trenger ikke å omgå mellomlageret for å forbli gyldig

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

Hvor mappen hører hjemme i en ekte utrulling

Tre egenskaper avgjør dette: mappen må være skrivbar for kontoen tjenesten kjører som, den bør ligge på lokal lagring snarere enn en nettverks-share, og den bør ikke være inne i en katalog som et utrullingstrinn visker ut. Et mellomlager på en share gjør hver bom til en rundtur og hvert treff til to; et mellomlager under en programmappe som installereren gjenoppretter er et mellomlager som starter kaldt etter hver oppdatering

For tjenester med flere instanser, gi hver instans sin egen mappe med mindre du har bekreftet at lagringen håndterer samtidig atomisk erstatning slik du forventer. Kostnaden av en duplisert oppføring er én ekstra delmengde-passering; kostnaden av å feilsøke et kappløp om delt mellomlager er en ettermiddag

Når du bør gripe etter noe annet

Mellomlageret reduserer gjentatt arbeid. Det reduserer ikke arbeidet til det første dokumentet, og det hjelper ikke en arbeidsmengde hvis glyff-mengder aldri gjentar seg. Hvis utdataen din domineres av én enorm CJK-skrift brukt på tvers av uforutsigbar tekst, er den mer effektive spaken delmengde-lukkingen selv — hvilke glyffer som dras inn, og hvorfor — dekket i notatene om skriftdelmengde-lukking og formings-glyffer. Hvis gruppen din er treg av årsaker som viser seg ikke å være skrifter i det hele tatt, viser gjennomgangen av rapportutdata med skrifter og bilder hvor den andre tiden vanligvis går, og case-studien om EndDoc-skriftdelmengde-rekkefølgefeilen er en påminnelse om at delmengde-korrekthet og delmengde-hastighet er separate problemer

HotPDF er en VCL-PDF-komponent for Delphi og C++Builder, og delmengde-mellomlageret er del av biblioteket snarere enn en tilleggstjeneste, slik at en rapporttjener får det ved å angi én mappesti — se HotPDF-komponentsiden for den fullstendige skrift- og ytelsesfunksjonslisten