Zdravím, znám rozdíl mezi synchronním a neblokujícím IO. Nedávno jsem se dostal k projektu v Go, kde je celý kód napsán synchronně, ale architekt tvrdí, že celá aplikace používá NIO (a testy výkonu tomu víceméně odpovídají). Je tu nějaký odborník, který by mi mohl vysvětlit, jak toho v Go dosáhli při použití sekvenčního kódu? Zběžně jsem prošel dokumentaci ke Go, ale na nic konkrétního jsem nenarazil.
V Go som sice nenapisal ani ciarku, ale vysvetlenie je velmi jednoduche. Aj ked sa zda, ze kod je synchronny, predpokladam, ze vsetky zdanlivo blokujuce I/O operacie sa deju v tele gorutin. Gorutiny maju vlastny stack. Ked gorutina robi zdanlivo blokujuce volanie, skutocne tazke vlakno, na ktorom je v tom case spustena/namultiplexovana skoci v tom momente do schedulovacej casti go runtime-u a ako prve zafreezuje stack (a registre) gorutiny tak, aby ju bolo mozne spustit od tohto bodu opat, t.j. ked budu pre nu ready data, ktore by bola byvala nacitala/zapisala. Uvolnene vlakno pozrie stavy otvorenych NIO deskriptorov a ak pribudli nejake data pre nejaku inu z predoslych gorutin, tieto data pripravi a dotycnu gorutinu spusti (da jej data na stack a zacne vykonavat telo gorutiny) od bodu kedy bola zafreezovana aj s datami. Vtip je v tom, ze tazke vlakno by nemohlo robit freeze/unfreeze stackov gorutin keby samo robilo blokujuce volania cez OS, lebo by ho blokol OS scheduler. Z toho vyplyvaju najmenej tieto body: takato forma schedulovania sa technicky bez NIO ani robit neda, go runtime ma vlastny workstealing scheduler, ktory v podstate simuluje spravanie akehosi lahkeho OS schedulera, ale iba pre gorutiny. Pokial go scheduler ma co robit, drzi tazke vlakna zaneprazdnene(resp. vlakna sa sami drzia zaneprazdnene a ked nenajdu inu robotu [gorutinu, ktoru treba vykonat, lebo jej dotiekly data] u seba, idu nejaku ukradnut od inych tazkych vlakien, z ktorych scheduler pozostava).
http://blog.nindalf.com/how-goroutines-work/Ludia to nazyvaju kooperativny multitasking preto, ze gorutiny neprerusuje casovac, ale zdanlivo blokujuca I/O operacia, kedy sa gorutina dobrovolne zastavi, resp. tazke vlakno, ktore ju vyoknava zafreezuje jej stack a registre. Avsak od programatora je tato logika schovana za fasadou gorutinoveho zdanlivo blokujuceho API, takze sa zda, ze kod je synchronny-blokujuci. Z clanku hore ale vyplyva, ze aj go ma istu notaciu preemptivnosti a ze dokaze gorutinu pozastavit-zafreezovat pri najblizsiom vstupe do funkcie, keby velmi zatazovala procesor.