Rehellinen load/save -benchmark PDF Library for Delphille mittaa LoadFromFile- ja SaveToFile-kutsujen keston QueryPerformanceCounterilla, säilyttää raakatikit ja laskurin taajuuden, ajaa perus- ja ehdokasversion vuorotellen A/B-, B/A-, A/B-pareina, kieltäytyy käynnistymästä kun prosessorin kuorma on yli 25 %, hylkää minkä tahansa tuloksen, jonka vaihteluvälin ja mediaanin suhde ylittää 15 %:n, ja heittää roskiin jokaisen mittauksen, jonka tallentama PDF kaatuu rakenteelliseen, renderöinti- tai semanttiseen validointiin. Lista kuulostaa byrokratialta siihen asti, kunnes ensimmäinen ”20 % nopeampi” -väite höyrystyy uusinnassa. Seuraavaksi kerrotaan, miten erillinen corpus-sondi ja sen vertailuajaja päätyivät tähän, mukaanlukien ajo, jossa kone oli yksinkertaisesti liian kiireinen mitattavaksi ja ajoke sanoi sen oikein
Miksi Delphin PDF-benchmark ilmoittaa ajaksi nolla sekuntia?
PDF:n latausbenchmark ilmoittaa nolla sekuntia silloin, kun sen kello tikittää karkeammin kuin se operaatio, jota se mittaa, ja GetTickCount64 on täsmälleen sellainen kello: se palauttaa millisekunteja, mutta Windowsilla se etenee vain kun järjestelmän ajastinkeskeytys laukeaa, tyypillisesti 15,6 ms välein. PDF Library for Delphin jättitiedostobenchmark-demossa FPC-portti käytti sitä, koska TStopwatch ei ole saatavilla kyseisessä työkaluketjussa, ja se kirjaa kuluneen ajan kolmen desimaalin tarkkuudella. Pienen CAD-piirustuksen tai lyhyen tagatun asiakirjan lataus valmistuu reilusti yhden ajastinaskeleen sisällä, joten demo tulosti joskus 0.000 lataukselle, joka selvästi teki oikeata työtä
function ElapsedSeconds(StartTick: QWord): Double;
begin
Result:= (GetTickCount64- StartTick)/ 1000.0;
end;
// operaatiosilmukan sisällä
Lib:= TPDFlib.Create;
try
Lib.OnProgress:= Reporter.Progress;
Started:= GetTickCount64;
LoadCode:= Lib.LoadFromFile(InputFile, Password);
...
Nolla on huonompi kuin epätarkka luku, sillä jokainen sen päälle rakennettu vertailu jakaa sillä. Paritettu vertailuajaja katsoo minkä tahansa haaran, jonka minimi on nolla, epäjohtopäätöksiseksi perusteella ”Nollakesto estää mielekkään suhteen”, mikä on oikea kieltäytyminen, mutta se tarkoittaa myös sitä, että demon mittaukset jättivät mitta-aukon täsmälleen sinne missä lyhyet tiedostot elävät. Sama demo asentaa myös OnProgress-takin, joten sen mittaukset sisältävät takaisinkutsun kuormituksen, jota siisti load/save-mittaus ei saisi kantaa, ja arkistoidut demonumerot eivät ole vaihdettavissa mihinkään myöhemmin mitattuun
LoadFromFile- ja SaveToFile-ajoitus QueryPerformanceCounterilla
Erillinen konsolisondi Tests/CorpusLoadSave.dpr mittaa kaksi operaatiota per syötetiedosto QueryPerformanceCounterilla: LoadFromFile sekä PageCountin lukeminen, ja LoadFromFile, PageCount sekä SaveToFile. Jokainen operaatio saa tuoreen TPDFlib-instanssin eikä progressiotakaisinkutsua, ja instanssin konstruktori ja destruktori ovat ajastetun alueen ulkopuolella, kuten myös CSV:n kirjoitus ja koko tuotoksen validointi. Laskuri luetaan heti ennen latausta ja heti viimeisen kirjastokutsun jälkeen, ja LastErrorCode haetaan vasta toisen lukeman jälkeen
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');
Sondi kirjoittaa raakatikkimäärän ja laskurin taajuuden johdettujen sekuntien viereen, yhdeksällä desimaalilla ja kiinteällä .-desimaalierottimella, joten kuka tahansa voi laskea osamäärän uudelleen CSV:stä sen sijaan että uskoisi sitä sokeasti. FPC Win64 -koosteessa CAD-näyte latautui 8 888 tikissä taajuudella 10 000 000 tikkiä sekunnissa, kirjattuna 0.000888800 sekuntina — havainto, jonka vanha ajastin olisi pyöristänyt nollaksi. Sondi ei tarkoituksella leikkaa lyhyitä arvoja, korvaa minimikestolla tai vähennä arvioitua ajastimen overheadia, ja se kirjoittaa silti molemmat rivit nollasta poikkeavalla poistumiskoodilla, kun kirjastokutsu epäonnistuu. Yhdeksän numeroa ei silti ole tarkkuutta: suurempi kirjattu tarkkuus ei kerro mitään toistettavuudesta, ja kohinaiset tai nollaiset havainnot pitää silti hylätä myöhemmissä vaiheissa
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));
Mikä tekee PDF:n load/save-ajoitusvertailusta luotettavan?
Ajoitusvertailu kahden PDF Library for Delphi -koosteen välillä on luotettava vain silloin, kun käynnistysjärjestys, käynnistysehdot ja vaihtelu ovat kaikki kontrolloituja ja kirjattuja, joten vertailuajaja ajaa vähintään kolme paria A/B-, B/A-, A/B-järjestyksessä. Aina ensin ajettava perusversio luovuttaa hiljaisesti ehdokkaalle lämpimämmän tiedostovälimuistin ja erilaisen lämpötilatilan; järjestyksen vuorottelu levittää tuon vinouman molemmille haaroille sen sijaan että lahjoittaisi sen yhdelle. Ennen jokaista haaraa ajaja tiivistää koko syötetiedoston SHA-256:lla, mikä sekä varmistaa ettei mikään muuttunut että esilukee samat tavut kummallekin haaralle, ja se tiivistää molemmat suoritettavat ja validointityökalut uudelleen jokaisen ajon jälkeen, ettei uudelleenkäännetty binääri hiipi sarjan keskelle
Sen jälkeen ajaja ottaa näytteen koko koneen prosessorikuormasta kerran sekunnissa ja käynnistää haaran vasta kun näyte laskee 25 %:iin tai alle, odottaen enintään 30 sekuntia ennen kuin kirjaa yrityksen hylätyksi. Tuo portti kontrolloi käynnistysehtoa eikä muuta: se ei eristä konetta ajon ajaksi, ja virransäästötila, lämpötilakuristus, taustatyö ja käyttöjärjestelmän välimuisti voivat silti liikuttaa lukuja. Siksi toinen suodatin on kaikessa yksinkertaisuudessaan tilastollinen. Jokaiselle operaatiolle ajaja laskee vaihteluvälin jaetuna mediaanilla perushaaralle, ehdokashaaralle ja paritettujen ehdokas/perus-suhteiden jakaumalle, ja jos jokin kolmesta ylittää 0,15:n, tulos leimataan kohinaiseksi sen sijaan että raportoitiin löydöksenä
Miksi identtisen binäärin kontrolli todistaa toistettavuuden, ei nopeutta?
Identtisen binäärin kontrolli ajaa samat suoritettavat perus- ja ehdokasversiona, joten suhde lähellä 1,0 voi todistaa vain sen, että mittausjärjestelmä toistaa itsensä; se ei voi koskaan osoittaa, että toteutus nopeutui. Ensimmäinen tiukka kontrolli 21.9.2026 käytti korkean resoluution FPC Win64 -sondia hyväksyttyä 70-sivuista tagattua opasta vasten, ja kaikki kuusi käynnistystä hylättiin, koska prosessorinäytteet liikkuivat välillä 26,5 % – 93,8 %. Raportti sisälsi epäonnistumisia eikä yhtään yhteenvetoa, mikä on täsmälleen se lopputulos, jonka haluat, kun kone on kiireinen. Saman päivän uusinta tavu identtisillä syötteillä, samalla sondisuoritettavalla ja muuttumattomilla kynnysarvoilla hyväksyi kaikki kuusi käynnistystä 3 sekunnin sisällä; jokainen vaihteluväli-mediaani-suhde osui väliin 0,019–0,054, ja suhteiden mediaanit olivat LoadFromFileille 1,0084 ja LoadFromFile + SaveToFilelle 0,9872
Se lukupari perustaa rajatun havaintoikkunan eikä mitään muuta. Kun kaksi binääriä eroavat, vakaa ajo leimataan kuvailevaksi vertailuksi, ja siinä todetaan suoraan, että suhteet ovat havaintoja, eivät tilastollista merkitsevyyttä tai nopeutusväitettä. Kuri kannattaa eniten silloin, kun validoit kohdennettuja optimointeja, kuten niitä, jotka kerrotaan artikkelissa PDF Library for Delphin profiloinnista ja kuumien polkujen korvaamisesta hash-indekseillä: profiloija kertoo, mihin aika kuluu, mutta vain kontrolloitu paritettu ajo oikeilla asiakirjoilla kertoo, selvisikö muutos kosketuksesta koko putken kanssa. Vielä yksi raja kannattaa sanoa ääneen — normal-save sisältää latauksen, ja huippukäyttämä, jonka ajaja kirjaa, on prosessinlaajuinen, joten mikään siitä ei ole muistia, jonka voi katsoa pelkän tallennuksen aiheuttamaksi
Kolme tuotosporttia ja neljän kääntäjän matriisi
Mikään PDF Library for Delphi -mittaus ei laske, ellei sen tuottama tiedosto mene läpi kolmesta riippumattomasta portista, sillä nopeasti rikkinäisen PDF:n kirjoittava tallennus ei ole nopeampi tallennus. Benchmark tarkistaa ensin, että molemmat operaatiot palauttivat 1:n ja ilmoittivat hyväksytyn sivumäärän, ja validoi sitten yksittäisen tallennetun PDF:n tässä järjestyksessä:
- Rakenne: riippumattoman PDF-tarkistimen on hyväksyttävä tallennettu tiedosto ilman virheitä tai varoituksia
- Renderöinti: jokainen sivu renderöidään oletustilassaan, ja sivukohtaisen kuva-SHA-256-joukon on täsmättävä täsmälleen hyväksytyn lähteen vertailurenderöintiin
- Ei-näkyvä semantiikka: erillinen semanttinen vertailu lähteeseen kattaa valittuja ominaisuuksia, joita pikselit eivät voi näyttää, mukaanlukien valinnaisen sisällön ja mittausrakenteet niiden dokumentoidussa laajuudessa
Näiden porttien paikallaan ollessa koko paikallinen corpusmatriisi ajoi sondin FPC Win32:lla, FPC Win64:llä, Delphi Win32:lla ja Delphi Win64:llä 12 hyväksytyn PDF:n yli, joissa oli yhteensä 1 612 lähteen sivua, tuottaen 48 näyte/kohde-paria ja 6 448 validoitua tuotossivua ilman valittuja semanttisia eroja. Kaikki 96 operaatiomittausta säilyttivät positiiviset raakalaskuriarvot, jotka olivat yhdenmukaisia ilmoitettujen sekuntien kanssa, ja kyseisiä arvoja ei aggregoida tahallaan kääntäjien yliseksi nopeustaulukoksi, koska matriisi on toiminnallista todistetta eikä kontrolloitu vertailu. Load/save-polku ei myöskään väitä purkavansa jokaista upotettua kuvaa, validoivansa allekirjoituksia, ajavansa XFA:a tai sertifioivansa PDF/UA:a; jos sinun tarvitsee arvioida renderöintiläpäisyä load/save-kustannuksen sijaan, rinnakkaisen sivujen renderöinnin ja säieturvallisuuden rajoitukset PDF Library for Delphissä ovat parempi lähtöpiste
Käytännön oppi on lyhyt: säilytä raakalaskurit, vuorottele järjestystä, aseta käynnistykselle portti, kieltäydy kohinaisesta vaihtelusta ja älä koskaan mittaa tuotosta, jota et ole validoinut. Nuo säännöt ovat se, mikä antaa PDF Library for Delphille mahdollisuuden sanoa ”ei mitattavaa muutosta” yhtä varmasti kuin ”nopeampi”, ja sama sondilähde kääntyy muuttumattomana Delphillä ja FPC:llä Win32:lle ja Win64:lle. Kirjaston, sen load/save-API:n ja tuettujen kääntäjien voi katsella PDF Library for Delphi -tuotesivulta