Vercel eksperimentālā nodaļa Vercel Labs 22. jūlijā publicēja GitHub kompilatoru scriptc, kas parastu TypeScript kodu pārvērš patstāvīgā native izpildfailā. Gatavajā failā nav ne Node, ne V8, ne kāda cita JavaScript dzinēja. README parādītais Fibonači piemērs sakompilējas 178 KB lielā failā, kas startē aptuveni 2,4 milisekundēs. Node tam pašam kodam prasa ap 47 ms.
Piecās dienās repozitorijs savāca 1595 zvaigznes un nokļuva Hacker News pirmajā lapā. Tur arī sākās strīds, jo pati pirmā revīzija repozitorijā pievieno 802 614 rindas 300 failos.
No tsc līdz clang
scriptc neraksta savu tipu pārbaudītāju. Kodu parsē un pārbauda īstais TypeScript kompilators. No tā rezultāta scriptc būvē tipizētu starpreprezentāciju, tālāk to nodod LLVM aizmugurei vai ģenerē C kodu, ko kompilē clang. C aizmugure paliek kā atsauces variants: ar --backend c var izlasīt ģenerēto C kodu ar norādēm uz sākotnējām rindām.
Izpildlaiks ir uzrakstīts C valodā. Vērtības skaita atsauces, ciklus savāc atsevišķs kolektors. async un await strādā uz stackful fibers ar Node atbilstošu izpildes kārtību, notikumu cilpa balstās uz kqueue. Katra izpildlaika daļa ir atsevišķa saites vienība, tāpēc binārais fails ietver tikai to, ko programma tiešām lieto.
Statiski kompilējas arī tā Node API daļa, kas vajadzīga serveriem: fs, path, process, child_process, crypto, zlib, taimeri, signāli, net, http, https un tls ar iekļautu mbedTLS. Klāt ir fetch ar WHATWG straumēm un AbortSignal. Autori raksta, ka reāli starpniekserveri sakompilējas.
Trīs līmeņi, kas vienmēr redzami
Katru konstrukciju scriptc iedala vienā no trim grupām. Noklusējums ir statiskā kompilācija bez dzinēja. Ar karogu --dynamic binārajā failā iebūvē quickjs-ng, kas aizņem ap 620 KB un izpilda to, kas statiski nav iespējams: npm pakotņu piegādāto JavaScript un any tipa kodu. Trešā grupa ir atteikums. Kompilators izmet kļūdu ar savu kodu, piemēram, SC1090 funkcijām ar neobligātiem parametriem, kas tiek lietotas kā vērtības.
Komanda scriptc coverage parāda sadalījumu skaitļos: cik teikumu analizēts, cik no tiem kompilējas statiski un kuri konstrukti bloķē pārējos. Vērtības, kas no dinamiskā līmeņa atgriežas statiskajā kodā, tiek pārbaudītas izpildes laikā, tāpēc nepatiess tips met TypeError, nevis bojā atmiņu.
Binārajā failā nav JavaScript dzinēja, bet pēc izvēles tam pieliek 620 KB lielu quickjs. Atmet JavaScript, taču patur pudeli galda atvilktnē.
Tā scriptc solījumu Hacker News diskusijā raksturoja lietotājs luciana1u. Vārds native attiecas uz noklusējuma režīmu, ne uz to, kas notiek ar īstu node_modules mapi.
Ātrs starts, lēnas cilpas
Pirmo publisko neatkarīgo mērījumu veica Elias Watson, kas Primes etalonu pārnesa uz scriptc. Baitu masīva variantā, kas scriptc padodas vislabāk, programma izpildījās 7,5 reizes lēnāk par Node 24. Tajā pašā testā tā startēja 12 reizes ātrāk (1,5 ms pret 18,6 ms), patērēja 2,5 MiB atmiņas pret Node 181 MiB un sanāca kā viens 370 KB izpildfails bez ārējām atkarībām.
Aritmētikas ātrums izriet no tā, ko README atzīst pats: visi skaitļi tiek attēloti kā 64 bitu peldošā punkta vērtības, tāpat kā JavaScript. Veselu skaitļu izsecināšana un piederības analīze vēl tikai ir plānos. Tā ir viena no vecākajām optimizācijām, ar ko numeriskās valodas kļūst ātras. Šobrīd tā nav ieslēgta.
Pārējie README skaitļi: statisks binārais fails 170 līdz 200 KB, ar --dynamic un iekļautām atkarībām ap 3 MB. Node vienfaila būvējums salīdzinājumam sver 60 līdz 100 MB. Atmiņas patēriņš 1 līdz 4 MB pret Node 67 līdz 116 MB.
802 614 rindas vienā revīzijā
Pirmo revīziju ar nosaukumu init 22. jūlijā plkst. 23:08 UTC iesūtīja Chris Tate. Tajā ir 802 614 pievienotas rindas 300 failos. Piecās dienās sekoja vēl 285 revīzijas un npm reģistrā nonāca 18 versijas līdz 0.0.17.
Hacker News komentāros šis skaitlis kļuva par galveno argumentu pret projektu. Lietotājs h1fra rakstīja, ka piecu dienu vecs, ar modeļa palīdzību uzrakstīts projekts jau savācis pusotru tūkstoti zvaigžņu un pēc dažiem mēnešiem paliks bez uzturēšanas. Lietotājs pmkary pamēģināja scriptc uz visiem saviem lokālajiem projektiem un ziņoja, ka coverage katrā no tiem izdod simtiem kļūdu, tāpēc praksē nekompilējas neviens.
README valoda arī pieķer aci. Simon Willison, kuru daļa diskusijas dalībnieku sajauca ar projekta autoru, no faila izņēma divus vārdus. Sadaļas virsraksts pirms tam bija “Escape hatches, honestly priced”.
Ko projekts liek pretī
Repozitorijā ir divas testu joslas. Katra no vairāk nekā 800 korpusa programmām tiek izpildīta gan Node vidē, gan kā native binārais fails. Standarta izvads, kļūdu izvads un izejas kods jāsakrīt baitu līmenī. Skaitļu formatēšana pārbaudīta pret Node uz miljona dubultprecizitātes vērtību. Otrā josla to pašu korpusu izpilda zem AddressSanitizer ar atsauču skaita auditu. Atmiņas noplūde vai lietošana pēc atbrīvošanas nozīmē būvējuma kļūdu. Dažus desmitus apzinātu atšķirību no Node autori uzskaitījuši un numurējuši atsevišķi.
Ir arī divas izejas ārpus TypeScript. Ar comptime kodu izpilda būvēšanas laikā izolētā VM kompilatora iekšienē un rezultātu iebūvē failā kā literāli. Ar --ffi tikai deklarētas TypeScript signatūras piesien tiešiem C ABI izsaukumiem un pievieno manifestā norādītās bibliotēkas.
Galvenā platforma ir macOS arm64. Linux un Windows failus scriptc būvē ar krustkompilāciju, katram ir sava diferenciālo testu josla. Instalēšanai vajag npm install -g scriptc un clang, kas macOS nāk kopā ar Xcode komandrindas rīkiem. Jaunākā npm versija 0.0.17 publicēta 27. jūlijā plkst. 02:22 UTC, licence Apache 2.0.
Komentāri
Šim rakstam vēl nav komentāru. Esi pirmais, kurš dalās ar savu viedokli.