Node.js vs. Go

V Techband je naším cieľom tvoriť IT základňu hviezdnych developerov a mimo iného podporovať ich a aj širšiu verejnosť, v osobnostnom a profesionálnom rozvoji v oblasti IT a technológií. Práve preto sme sa koncom roka 2020 rozhodli spustiť sériu Techband meetup-ov zameraných na rozvoj hard-skills, konkrétne na jednu z najpopulárnejších technológii – JavaScript.

V tomto článku vám prinášame bližšie predstavenie témy “Node.js vs. Go”, o ktorej na poslednom z našich JavaScript meetup-ov porozprával náš speaker Josef Podaný, CTO v CloudTalk. 

 

Na čo sa pozerať pri voľbe programovacieho jazyka pre backend?

1.) Rýchlosť

Každý developer dnes hľadá nejaký programovací jazyk alebo výrazový prostriedok, ktorý mu dovolí čo najrýchlejšie písať kód a vyvíjať aplikáciu. Problém však je, že sa v dnešnej dobe väčšinou nikto nepozerá na to, ako rýchlo rôzne úkony pracujú a ako sú veci z pohľadu výkonnosti nastavené. Nikto si teda neuvedomuje, ako to celé pri návrhu architektúry aplikácie funguje od napísania kódu až po delivery k užívateľovi a čo je od čoho závislé. V nižšie priloženej tabuľke môžete vidieť relatívne hodnoty toho, ako rýchle sú rozličné úkony. 

 

Execute typical instruction 1/1 000 000 000 sec = 1 nanosec
Fetch from L1 cache memory 0.5 nanosec
Branch misprediction 5 nanosec
Fetch from L2 cache memory 7 nanosec
Mutx lock / unlock 25 nanosec
Fetch from main memory 100 nanosec
Send 2K bytes over 1 Gbps network 20 000 nanosec
Read 1MB sequentially from memory 250 000 nanosec
Fetch from new disk location (seek) 8 000 000 nanosec
Read 1MB sequentially from disk 20 000 000 nanosec

 

Pýtate sa, ako tieto informácie využiť v praxi? Ak napríklad viete, že načítanie z cache na procesore trvá 0.5 nanosekundy a načítanie súboru z HDD trvá rádovo 8 miliónov nanosekúnd, tak je zrejmé, že v prípade tvorby nejakej performance-heavy a vysoko výkonnej aplikácie je potrebné prispôsobiť architektúru návrhu a výber komponentov práve týmto kritériám. Ak si teda myslíte, že napíšete rýchlu aplikáciu, ktorá bude po sieti čítať nejaké distribuované informácie z Rabbit-u alebo prístroja, ktorý je od vás vzdialený pol zemegule, a popritom bude v nejakom čase bežať rádovo menej ako 20 milisekúnd, tak ste na veľkom omyle.

Pri písaní akejkoľvek aplikácie je preto vždy potrebné uvedomiť si, akými prostriedkami v danom programovacom jazyku disponujete a čo musíte v rámci návrhu architektúry zohľadniť práve preto, aby ste dokázali dosiahnuť želaných časových a výkonových kritérií. Keď teda navrhujete nejakú softvérovú aplikáciu, tak už na začiatku vývoja je potrebné mať jasno v tom, aké sú potenciálne problémy, ktoré môžu vzniknúť, alebo tiež, aké budú jednotlivé komponenty aplikácie, ako budú fungovať a s čím budú komunikovať. Až na základe toho by ste si následne mali vybrať samotný programovací jazyk.

 

2.) Synchrónnosť vs. asynchrónnosť

Toto je rovnako jedným z úskalí, ktorému sa pri výbere programovacieho jazyku nevenuje až taká veľká pozornosť, ako by sa mu venovať mala. Rozprávame sa tu o spôsobe programovania alebo práce v programovacom module, kde kód funguje synchrónne alebo asynchrónne.

Najväčší rozdiel v rámci tejto problematiky môžete vidieť pri porovnaní PHP a JavaScript-u. PHP je bez akejkoľvek pridanej knižnice synchrónnym programovacím jazykom, čo znamená, že kód sa exekuuje presne tak, ako je napísaný. Naopak, v rámci JavaScript-u je kód procesovaný asynchrónne, čo znamená, že už nie je procesovaný tak, ako bol napísaný, ale tak, ako sa registrujú nejaké asynchrónne funkcie v rámci call-stacku. 

Asynchrónne programovanie ako také prinášalo v dobe pred synchrónnym takzvaný call-back hell, kde programátor nedokázal jednoduchým spôsobom pekne popisovať exekuovanie daného kódu, ako je dnes možné napríklad v jazykoch ako Python alebo PHP. To znamená, že čitateľnosť, testovanie a debugovanie kódu bolo extrémne zložité, nehovoriac o pokusoch sa monitorovať alebo ďalej zlepšovať určité bench-marky a iné výkonové testy, ktorými by ste dokázali posúvať aplikáciu na vyššiu úroveň. 

Voľba medzi synchrónnosťou a asynchrónnosťou kódu hrá teda pomerne významnú úlohu pri výbere vhodného programovacieho jazyka pre projekt. Má to vplyv na to, ako budete dizajnovať volanie funkcií a vnútornú architektúru jednotlivých blokov programu, kde sa napokon dostávate až k prevedeniu nejakej refaktorizácie kódu do malých častí a jednotiek.

 

3.) Vykonávanie kódu konkurentne vs. paralelne

Táto problematika nadväzuje práve na voľbu medzi synchrónnosťou a asynchrónnosťou, pretože na základe nej bude kód vykonávaný konkurentne alebo paralelne.

Problémom paralelného programovania sa často zaoberajú začínajúci programátori práve na vysokých školách, kde sa učia navrhovať systém tak, aby dokázal bežať zároveň na viacerých procesoroch. To je samotná disciplína, ktorá sa neskôr v reálnom svete pri práci na business development projektoch, kde je potrebné tvoriť aplikácie čo najrýchlejšie a dávať ich hneď von, nedá tak dobre uplatniť. Z toho dôvodu je developerom oveľa bližšie využívanie konkurentného prístupu, kde dokážu jednoduchšie implementovať zdanie a funkcionality paralelne bežiacich aplikácií. 

Toto je teda druhá paradigma, ktorá stojí vedľa problému synchrónnosť vs. asynchrónnosť a ktorá rozhoduje o tom, akým spôsobom budete schopní škálovať svoje aplikácie v rámci počítača, na ktorom daný server beží. Toto sa dá tiež prepojiť aj s už spomínanou rýchlosťou úkonov a vieme skonštatovať, že čokoľvek, čo beží na jednom prístroji bude oveľa lepšie z hľadiska výkonu, ako to, čo beží na rozličných, distribuovaných alebo oddelených strojoch.

Ideálom by malo byť posunúť sa vo finále do paralelného sveta, kde dokážete využívať viacero jadier počítača (asynchrónne programovanie však napríklad dovoľuje využívať len konkurentný prístup v rámci jedného jadra a aj to predstavuje pomerne nepohodlné, nepresné a skôr intuitívne programovanie). 

 

JS projekty

Pozrime sa teraz konkrétne na Node.js a Go

V prípade Node.js nie ste nikdy schopní dosiahnuť to, že z vášho serveru alebo počítača vyžmýkate úplne maximum toho, čo vám vie ponúknuť. Ak sa rozprávame o paralelnom programovaní, tak tam úplne zlyháva, pretože v samotnom Node.js nie sú paralelné funkcie vôbec implementované a okrem toho je vo všeobecnosti single-threaded. Rovnako, tým, že je Node.js asynchrónny, tak napríklad nedokáže ukladať neblokujúce operácie v rámci call-stacku a dostávate sa do niečoho, čo prezentuje aj tento obrázok:

Programovací jazyk Go prináša odpovede na všetky tieto vyššie spomenuté otázky a rieši tak všetky problémy, s ktorými sa stretávame pri využití Node.js. Inými slovami Go prináša vlastné interné dátové typy a ďalšie jazykové konštrukcie, ktoré počítajú práve s tým, že máte pred sebou stroj s viacerými procesormi a potrebujete synchronizovať spúšťané sub-tasky, ktoré zároveň bežia v stotisícoch. Vy tak máte na úrovni programovacieho jazyka naozaj efektívny nástroj alebo sadu nástrojov, ktoré vám umožnia písať kód tak, aby vyzeral skoro paralelne. To znamená, že dokážete v Go napísať aplikáciu, ktorá naplno využije potenciál vašich multiprocesorových strojov a dokáže spätne využiť konkurentný prístup. 

 

Čo presne je Go?

Go je jazyk, ktorý vznikol už pred 12 rokmi, takže nie je žiadnou novinkou, aj keď jeho adaptácia na Slovensku a v Česku prichádza viac masívnejšie až teraz. Jeho 12 rokov na trhu však znamená, že ako jazyk je výrazne vyspelý a jeho známkou stability je to, že aktuálne funguje vo verzii 1.17 (z pohľadu API sa nikdy nerozbil a nikdy neprišli žiadne zmeny, ktoré by nejakým spôsobom boli prekážkou pre upgrade v produkciách), zatiaľ čo Node.js je aktuálne vo verzii 17 a každý mesiac zvyknú prichádzať nové a nové (to znamená, že z hľadiska produkcie je pomerne náročné udržať pod Node.js stabilný kód). V budúcnosti je možné, že príde Go 2.0, avšak aj ten bude kompatibilný so staršími verziami.

Okrem iného je Go open-source, ktorý vznikol v Google, teda je výsledkom práce niekoľkých pôvodných developerov, ktorí ešte v 70-tych rokoch navrhovali C a podobné jazyky. Cieľom bolo vytvoriť niečo, čo im pomôže paralyzovať procesy a aplikácie na viac-procesorových strojoch so silnou podporou networkingu a s veľkými objemami dát.

Jednou z jeho veľkých výhod oproti Node.js je práve to, že Go samé o sebe obsahuje všetky konštrukty potrebné na to, aby ste dokázali písať konkurentné a paralelné aplikácie. Teda na to, aby ste napísali aplikáciu, ktorá dokáže využiť všetky jadrá počítača, nepotrebujete v Go žiadnu externú knižnicu a samotný zápis kódu je z pohľadu vývojára bližšie skôr ku klasickému C a podobným jazykom. Navyše do kódu neprináša žiadne anomálie typu asynchrónny kód v Node.js, teda je ďaleko lepšie čitateľný a ľahšie sa udržuje. Ďalšou výhodou je aj toolset, ktorý so sebou sám nesie a vďaka ktorému dokážete kód ako taký dobre testovať. Súčasťou Go sú aj tooly pre benchmarkovanie kódu na úrovni jednotlivých funkcií, čiže to, čo v rámci Node.js nedokážete urobiť jednoduchým spôsobom. Tým pádom viete cez Go významne a jednoducho ovplyvňovať samotný performance danej aplikácie z pohľadu toho, koľko a kde trávi procesor čas, koľko alokačných operácií vykonáva alebo ako mohutne pracuje s garbage kolektorom. To sú kľúčové údaje, ktoré tvoria výsledný obraz toho, ako je daná aplikácia výkonovo úspešná.

 

Sledujte naše aktivity aj na našom Instagram a Facebook profile alebo na LinkedIn.