Poctivý load/save benchmark pre PDF Library for Delphi meria LoadFromFile a SaveToFile pomocou QueryPerformanceCounter, necháva si surové ticky a frekvenciu čítača, púšťa baseline a kandidáta v striedavých pároch A/B, B/A, A/B, odmieta štartovať, kým záťaž CPU sedí nad 25 %, zamietne každý výsledok, ktorého rozptyl range-to-median presahuje 15 %, a vyhodí každé meranie, ktorého uložené PDF neprejde štruktúrnou, renderovacou ani sémantickou validáciou. Tento zoznam vyzerá byrokraticky, kým vám nárok „rýchlejšie o 20 %" prvýkrát nevyparí sa pri opakovaní behu. Nasleduje to, ako sa k tomu dostala špecializovaná corpus sonda a jej porovnávací runner, vrátane behu, pri ktorom bol stroj jednoducho príliš zaneprázdnený na to, aby sa dalo čokoľvek merať, a harness to správne vyhlásil
Prečo PDF benchmark v Delphi vypíše nula sekúnd?
PDF load benchmark hlási nula sekúnd, keď jeho hodiny tikajú hrubšie, než je operácia, ktorú meria, a GetTickCount64 je presne takýto typ hodín: vracia milisekundy, ale na Windowse postupuje iba pri výstrele prerušenia systémového časovača, typicky každých 15,6 ms. FPC port dema benchmarku veľkých súborov v PDF Library for Delphi ho použil, pretože TStopwatch v tom toolchaini nie je k dispozícii, a zapisuje uplynulý čas na tri desatinné miesta. Načítanie malej CAD kresby alebo krátkeho tagged dokumentu skončí pohodlne vnútri jedného kroku časovača, takže demo niekedy vypísalo 0.000 pre načítanie, ktoré zjavne odrobilo poriadnu prácu
function ElapsedSeconds(StartTick: QWord): Double;
begin
Result:= (GetTickCount64- StartTick)/ 1000.0;
end;
// vnútri slučky operácie
Lib:= TPDFlib.Create;
try
Lib.OnProgress:= Reporter.Progress;
Started:= GetTickCount64;
LoadCode:= Lib.LoadFromFile(InputFile, Password);
...
Nula je horšia než nepresné číslo, pretože každé porovnanie, ktoré na nej postavíte, sa ňou delí. Párový porovnávací runner označí akúkoľvek vetvu s nulovým minimom za nepresvedčivú s odôvodnením „Zero duration prevents a meaningful ratio", čo je správne odmietnutie, ale znamená to aj to, že timingy dema zanechali meraciu medzeru presne tam, kde žijú krátke súbory. To isté demo inštaluje aj callback OnProgress, takže jeho timingy nesú réžiu callbacku, ktorú čisté load/save meranie niesť nemá, a archivované čísla z dema sú nezameniteľné s čímkoľvek nameraným neskôr
Meranie LoadFromFile a SaveToFile pomocou QueryPerformanceCounter
Špecializovaná konzolová sonda Tests/CorpusLoadSave.dpr meria na každý vstupný súbor dve operácie pomocou QueryPerformanceCounter: LoadFromFile plus čítanie PageCount a LoadFromFile plus PageCount plus SaveToFile. Každá operácia dostane čerstvú inštanciu TPDFlib a žiadny progress callback, konštruktor a deštruktor inštancie sedia mimo meranej oblasti, rovnako ako zápis CSV a všetka validácia výstupu. Čítač sa číta tesne pred načítaním a tesne po poslednom volaní do knižnice a LastErrorCode sa získava až po druhom čítaní
Lib:= TPDFlib.Create;
try
if not QueryPerformanceCounter(Started) then
raise Exception.Create('Performance counter unavailable');
Code:= Lib.LoadFromFile(WideString(SourceFile), '');
if Code= 1 then
begin
Pages:= Lib.PageCount;
if Save then Code:= Lib.SaveToFile(WideString(SavedFile));
end;
if not QueryPerformanceCounter(Finished) then
raise Exception.Create('Performance counter unavailable');
ErrorCode:= Lib.LastErrorCode;
finally
Lib.Free;
end;
Ticks:= Finished- Started;
if Ticks< 0 then
raise Exception.Create('Performance counter moved backwards');
Sonda zapisuje surový počet tickov a frekvenciu čítača vedľa odvodených sekúnd, formátovaných na deväť desatinných miest s pevným oddeľovačom ., takže si ktokoľvek môže kvocient z CSV vypočítať znovu namiesto toho, aby mu veril. Na zostavení FPC Win64 sa vzorka CAD načítala za 8 888 tickov pri 10 000 000 tickov za sekundu, zapísané ako 0.000888800 sekundy — pozorovanie, ktoré by starý časovač zaokrúhlil na nulu. Sonda zámerne neskracuje krátke hodnoty, nenahrádza ich minimálnou dobou ani neodpočítava odhadovanú réžiu časovača a aj pri zlyhaní volania knižnice zapíše oba riadky s nenulovým exit kódom. Deväť číslic ale nie je presnosť: viac zaznamenaných desatinných miest nič nehovorí o opakovateľnosti a šumné alebo nulové pozorovania treba aj naďalej odmietať v ďalších krokoch
if not QueryPerformanceFrequency(Frequency) or (Frequency<= 0) then
raise Exception.Create('Performance counter frequency unavailable');
NumberFormat:= TFormatSettings.Create;
NumberFormat.DecimalSeparator:= '.';
...
Rows.Add(CSV(ExtractFileName(SourceFile))+ ','+ CSV(Operation)+ ','+
FormatFloat('0.000000000', Ticks/ Frequency, NumberFormat)+ ','+
IntToStr(Code)+ ','+ IntToStr(ErrorCode)+ ','+ IntToStr(Pages)+ ','+
IntToStr(Ticks)+ ','+ IntToStr(Frequency));
Čo robí porovnanie timingov PDF Load/Save dôveryhodným?
Porovnanie timingov medzi dvoma zostaveniami PDF Library for Delphi je dôveryhodné len vtedy, keď sú štartovacie poradie, štartovacie podmienky aj rozptyl kontrolované a zaznamenané, takže porovnávací runner naplánuje aspoň tri páry v poradí A/B, B/A, A/B. Keď vždy beží najprv baseline, kandidát potichu dostane teplejšiu file cache a iný teplotný stav; striedanie poradia rozotrie toto skreslenie do oboch vetiev namiesto pripísania ho jednej. Pred každou vetvou runner hashuje kompletný vstupný súbor cez SHA-256, čím overí, že sa nič nezmenilo, a predčíta tie isté bajty pre obe vetvy, a po každom behu znovu hashuje oba spustiteľné súbory aj validačné nástroje, takže sa do stredu série neprepačí novo preložená binárka
Runner potom raz za sekundu vzorkuje celostrojové vyťaženie CPU a vetvu spustí, až keď vzorka klesne na 25 % alebo pod ňu, s čakaním maximálne 30 sekúnd, než zaznamená pokus ako zamietnutý. Táto brána kontroluje štartovaciu podmienku a nič viac: stroj počas behu neizoluje a stav napájania, tepelné škrtenie, práca na pozadí aj cache OS môžu čísla stále pohnúť. Preto je druhý filter štatistický v najprostejšom zmysle. Pre každú operáciu runner spočíta range delené mediánom pre vetvu baseline, vetvu kandidáta a rozdelenie párovaných pomerov kandidát/baseline, a ak ktorákoľvek z týchto troch hodnôt presiahne 0,15, výsledok sa označí ako noisy namiesto toho, aby sa hlásil ako zistenie
Prečo same-binary kontrola dokazuje opakovateľnosť, nie rýchlosť?
Same-binary kontrola púšťa ako baseline aj kandidáta identické spustiteľné súbory, takže pomer blízko 1,0 môže dokázať len to, že sa meracie zariadenie správa opakovateľne; nikdy nemôže ukázať, že nejaká implementácia zrýchlila. Prvá prísna kontrola 21. 9. 2026 použila high-resolution FPC Win64 sondu proti prijatej tagged príručke o 70 stranách a všetkých šesť štartov bolo zamietnutých, pretože vzorky CPU sa pohybovali od 26,5 % do 93,8 %. Report obsahoval zlyhania a žiadne agregáty, čo je presne ten výsledok, ktorý chcete, keď je stroj zaneprázdnený. Opakovanie v ten istý deň s bajtovo identickými vstupmi, tým istým spustiteľným súborom sondy a nezmenenými prahmi prijalo všetkých šesť štartov do 3 sekúnd; každý rozptyl range-to-median sa skončil medzi 0,019 a 0,054 a mediány pomerov boli 1,0084 pre LoadFromFile a 0,9872 pre LoadFromFile + SaveToFile
Tá dvojica čísel zakladá kvalifikované pozorovacie okno a nič viac. Keď sa dve binárky líšia, stabilný beh sa označí ako deskriptívne porovnanie s explicitnou poznámkou, že pomery sú pozorovania, nie štatistická významnosť ani nárok na zrýchlenie. Táto disciplína má najväčší význam, keď validujete cielené optimalizácie, ako tie opísané v článku o profilovaní PDF Library for Delphi a náhrade hot ciest hash indexmi: profiler povie, kam čas odchádza, ale či zmena prežila stretnutie s celým pipeline, povie len kontrolovaný párovaný beh na reálnych dokumentoch. Ešte jedna hranica, ktorú stojí za to povedať nahlas — normal-save zahŕňa načítanie a peak working set, ktorý runner zaznamenáva, je celoprosesový, takže žiadna časť z nej nie je pamäť pripisovateľná len ukladaniu
Tri výstupné brány a matica štyroch kompilátorov
Žiadny timing PDF Library for Delphi sa neráta, pokiaľ súbor, ktorý vyprodukoval, neprejde tromi nezávislými bránami, pretože uloženie, ktoré rýchlo zapíše pokazené PDF, nie je rýchlejšie uloženie. Benchmark najprv skontroluje, že obe operácie vrátili 1 a nahlásili prijatý počet strán, a potom validuje jediné uložené PDF v tomto poradí:
- Štruktúra: nezávislý PDF checker musí prepustiť uložený súbor bez chýb a varovaní
- Renderovanie: každá strana sa renderuje v predvolenom stave a sada SHA-256 obrázkov na stranu sa musí presne zhodovať s referenčným renderom prijatého zdroja
- Nevizuálna sémantika: samostatné sémantické porovnanie so zdrojom pokrýva vybrané vlastnosti, ktoré pixely neukážu, vrátane štruktúr optional content a meraní v rámci ich zdokumentovaného rozsahu
S týmito bránami prebehla plná lokálna corpus matica sondu na FPC Win32, FPC Win64, Delphi Win32 a Delphi Win64 cez 12 prijatých PDF s 1 612 zdrojovými stranami, čo dalo 48 párov sample/target a 6 448 validovaných výstupných strán bez vybraných sémantických rozdielov. Všetkých 96 meraní operácií si ponechalo kladné surové hodnoty čítača konzistentné s hlásenými sekundami a tieto hodnoty sa zámerne neagregujú do cross-kompilátorovej tabuľky rýchlosti, lebo matica je funkčný dôkaz, nie kontrolované porovnanie. Load/save cesta tiež netvrdí, že dekóduje každý vložený obrázok, validuje podpisy, vykonáva XFA alebo certifikuje PDF/UA; ak potrebujete posúdiť priepustnosť renderovania, nie náklady load/save, lepším východiskom sú obmedzenia concurrency v článku o paralelnom renderovaní strán a thread safety v PDF Library for Delphi
Praktické poučenie je krátke: nechávajte si surové čítače, striedajte poradie, strážte štart, odmietajte šumné rozptyly a nikdy nemerajte výstup, ktorý ste nevalidovali. Vďaka týmto pravidlám môže PDF Library for Delphi povedať „žiadna merateľná zmena" s rovnakou istotou ako „rýchlejšie" a ten istý zdroják sondy sa preloží bez zmeny na Delphi aj FPC pre Win32 a Win64. Knižnicu, jej load/save API a podporované kompilátory si môžete pozrieť na stránke produktu PDF Library for Delphi