Zod shēmu var pārvērst par parastu JavaScript funkciju jau būvēšanas laikā, un rezultāts uz liela objekta ir līdz 73 reizēm ātrāka validācija nekā tas pats Zod izpildlaikā. Divi atsevišķi projekti — zod-compiler un zod-aot — dara vienu un to pašu: nolasa eksportētās shēmas kompilācijas brīdī un ģenerē tiešu pārbaudes kodu, kas apiet Zod izpildlaika mašīnu. Pirmkodā neko mainīt nevajag — pietiek pievienot spraudni būvēšanas rīkam.
Skaitļi ir atkarīgi no shēmas. zod-compiler README objektam ar 100 laukiem uzrāda 73 reizes ātrāku pārbaudi nekā Zod v4, bet kļūdainai ievadei vidēja izmēra objektā — 194 reizes. Uz vienkāršas virknes ieguvums ir vien 1,1 reize. Jo lielāka un dziļāka shēma, jo lielāka starpība.
Kāpēc Zod izpildlaikā ir lēns
Zod shēma ir objektu koks ar metodēm. Katrā parse() izsaukumā validators šo koku pārstaigā no jauna: nosaka katra mezgla tipu, izsauc .min(), .email() un pārējās pārbaudes caur konveijeru, veido kļūdu objektus ar ceļiem un metadatiem arī tad, kad ievade ir derīga, un piešķir atmiņu starpstruktūrām. Shēma ar 100 laukiem nozīmē simtiem mezglu apstaigāšanu katrā izsaukumā, lai gan pati shēma nekad nemainās.
Zod v4 daļu no tā jau atrisināja. Pirmajā parse() izsaukumā tas ģenerē specializētu objektu pārbaudes kodu kā virkni, kompilē to ar new Function() un saglabā kešā. Tas noņem objekta līmeņa dispečeru un dod 1,3–4,5 reizes paātrinājumu, kā skaidro wakita181009 tehniskais apraksts. Bet katra lauka pārbaude joprojām izsauc shape[key]._zod.run(), primitīvu pārbaudes konveijers joprojām darbojas, un Set, Map un Record vispār nesaņem šo optimizāciju.
Divfāžu ceļš
AOT (ahead-of-time) kompilācija noņem to, ko JIT atstāj. Ģenerētais kods ir pilnībā iekļauts vienā funkcijā: nav koka apstaigāšanas, nav konveijera, nav izpildlaika dispečera. Abi projekti ievieš vienu un to pašu shēmu ar diviem ceļiem.
Ātrais ceļš pārbauda visu ievadi ar vienu Būla izteiksmju virkni un nulli atmiņas piešķiršanu, un derīgas ievades gadījumā atgriežas nekavējoties. Lēnais ceļš, kas savāc kļūdas, ieslēdzas tikai tad, kad ātrais ceļš neizdodas.
Praksē tas nozīmē, ka derīgi dati iziet cauri vienai if pārbaudei, nevis desmitiem funkciju izsaukumu. zod-aot mērījumi rāda lielu objektu ar 100 laukiem 627 tūkstošos operāciju sekundē — 54 reizes vairāk nekā Zod v4 11,6 tūkstoši. Kolekcijas (Set, Map) sasniedz 7,6 miljonus operāciju sekundē, kas ir 16–22 reizes ātrāk. Rekursīvas struktūras dod 7 reizes vairāk operāciju.
zod-compiler etalonos redzama tā pati aina no cita gala. Tuple pārbaude iet 2,6 reizes ātrāk, Set ar 20 elementiem — 17 reizes, Map ar 20 ierakstiem — 24 reizes, bet rekursīva struktūra ar 121 mezglu — 33 reizes. Skaitļi aug līdz ar shēmas apjomu, jo tieši lielās shēmās izpildlaika koka apstaigāšana maksā visvairāk.
Kur tas nestrādā
Ne katru shēmu var kompilēt. zod-compiler atkāpjas uz izpildlaika Zod, ja shēmā ir atgriezeniskie izsaukumi ar tvertiem mainīgajiem, superRefine, custom, preprocess vai neatrisināma lazy shēma. zod-aot līdzīgi netiek galā ar .transform(), .refine(), .default(), .coerce() un .catch(), bet rekursīvas shēmas šobrīd izmanto atkāpšanos caur z.lazy().
Atkāpšanās notiek klusi: shēma ar transformāciju vienkārši darbojas kā līdz šim, bez paātrinājuma un bez kļūdas. Tas nozīmē, ka lielākais ieguvums ir tur, kur validācija ir tīra — tipu un formāta pārbaudes bez blakusefektiem, tieši tas, ko API robeža parasti dara ar ienākošo JSON.
Kuru ņemt
zod-compiler jūnijā sasniedza versiju 1.14.0 ar BSD-3-Clause licenci un atbalsta Vite, webpack, esbuild, Rollup, Rolldown, rspack, Bun un Farm. Tam ir trīs režīmi: automātisks, kas pats atrod visas eksportētās shēmas, tiešs ar compile() apvalku, un CLI ģenerēšana bez būvēšanas rīka. zod-aot darbojas caur unplugin un tāpēc sedz to pašu būvēšanas rīku klāstu; tā autoDiscover režīms filtrē failus pēc Zod importa, ielādē pirmkodu, atrod eksportus ar iekšējo _zod.def struktūru un aizvieto tos ar kompilēto kodu, saglabājot sākotnējo API.
Ātrums pats par sevi nav jaunums. Typia jau sen ģenerē pārbaudes kodu no TypeScript tipiem, un AJV kompilē validatorus no JSON Schema. Abiem ir sava cena: Typia prasa TypeScript transformatoru un darbojas ar tipiem, ne shēmām, bet AJV liek uzturēt shēmas JSON Schema formātā. AOT pieeja pie Zod atšķiras ar to, ka shēmas paliek turpat, kur bija, ar tiem pašiem z.object() izsaukumiem un to pašu tipu izsecināšanu, kas jau ir projektā.
Abi risina vienu problēmu no dažādiem leņķiem, un abi prasa tikai spraudņa rindu būvēšanas konfigurācijā. Ja tavā projektā Zod validē lielus objektus vai kolekcijas karstajā ceļā — piemēram, API pieprasījumu apstrādē vai datu importā — starpība starp interpretētu koku un iekļautu funkciju būs redzama profilā.
Komentāri
Šim rakstam vēl nav komentāru. Esi pirmais, kurš dalās ar savu viedokli.