reklama

Node.js a multiplexed IO obecně

gll

Re:Node.js a multiplexed IO obecně
« Odpověď #30 kdy: 23. 04. 2017, 09:01:43 »
await je právě náhrada callbacků. Jak funguje non-blocking IO v Javě nebo C++ v jednom vlákně bez callbacků? Co umí Java navíc oproti C#, že nepotřebuje await nebo yield?
Blbě a nic. Nějaký důvod, proč to JS nemá pořešené stejně jako třeba Go?


Nevím. K podobným účelům se používaly generátory. Async funkce jsou jen syntaktický cukr pro speciální případ. Osobně v přístupu Go vidím jen zvýšenou komplexitu a žádnou výhodu.

reklama


čumil

Re:Node.js a multiplexed IO obecně
« Odpověď #31 kdy: 23. 04. 2017, 09:32:56 »
await je právě náhrada callbacků. Jak funguje non-blocking IO v Javě nebo C++ v jednom vlákně bez callbacků? Co umí Java navíc oproti C#, že nepotřebuje await nebo yield?
Blbě a nic. Nějaký důvod, proč to JS nemá pořešené stejně jako třeba Go?
Žeby byl JS starší hlavo dubová?
Nehledě na to že JS používá async operace pro úplně všechno, nejen IO. Go tu asynchronost před vývojářem schovává. To je někdy dobře a jindy na škodu.

andy

Re:Node.js a multiplexed IO obecně
« Odpověď #32 kdy: 23. 04. 2017, 11:00:17 »
Žeby byl JS starší hlavo dubová?
Nerozumím. Jakýkoliv jazyk, který podporuje user-thready to umí. Což je spousta jazyků, které podporovaly green-thready, a pokud dobře čtu, tak i ta Java dneska má many-to-many thready, takže to umí také.
Citace
Nehledě na to že JS používá async operace pro úplně všechno, nejen IO. Go tu asynchronost před vývojářem schovává. To je někdy dobře a jindy na škodu.
Go zas tak moc neumím, ale "na škodu" mi připadá v tomhle případě jako zoufat si, že nové jazyky nemají "goto". Jo, některé problémy se s "goto" řeší líp a někdy to může být i podstatně rychlejší.

Citace: gil
Osobně v přístupu Go vidím jen zvýšenou komplexitu a žádnou výhodu.
Teď nevím, o čem se tu bavíme... v pseudokódu:
Kód: [Vybrat]
text = readFile("soubor")
if (text = "a")
   text2 = readFile("xxx")
else
   text2 = readFile("yyy");
udelejNeco(text2);
# vs.

readFile("soubor", text -> if (text == "a") readFile("xxx", text2 -> udelejNeco(text2)) else readFile("yyy", text2 -> udelejNeco(text2)))

# vs. to same jako priklad 1, akorat s async await
Co je na příkladu 1 "zvýšená komplexita"? Naopak, takhle by měl vypadat všechen kód. Celý async await je snaha, se k tomuhle dostat, ale ve výsledků to prostě není pořádně composable (https://github.com/tc39/ecmascript-asyncawait/issues/7). Je to stejně blbě composable jako generátory třeba i v pythonu. Dobře to má udělaný Purescript v Aff monadu, jenomže to asi do vanilla JS jde propašovat dost těžko.

gll

Re:Node.js a multiplexed IO obecně
« Odpověď #33 kdy: 23. 04. 2017, 15:22:35 »
Žeby byl JS starší hlavo dubová?
Nerozumím. Jakýkoliv jazyk, který podporuje user-thready to umí. Což je spousta jazyků, které podporovaly green-thready, a pokud dobře čtu, tak i ta Java dneska má many-to-many thready, takže to umí také.

Python umí obojí. Vlákna mají větší paměťovou náročnost a musíte myslet na thread safety datových struktur a funkcí, atomicitu operací a synchronizaci. Případně používat zámky.

Citace
Nehledě na to že JS používá async operace pro úplně všechno, nejen IO. Go tu asynchronost před vývojářem schovává. To je někdy dobře a jindy na škodu.
Go zas tak moc neumím, ale "na škodu" mi připadá v tomhle případě jako zoufat si, že nové jazyky nemají "goto". Jo, některé problémy se s "goto" řeší líp a někdy to může být i podstatně rychlejší.

V JS máte jistotu, že posloupnost operací přistupující ke sdíleným prostředkům proběhne bez přerušení. V Go tu jistotu nemáte.

Citace: gil
Osobně v přístupu Go vidím jen zvýšenou komplexitu a žádnou výhodu.
Teď nevím, o čem se tu bavíme... v pseudokódu:
Kód: [Vybrat]
text = readFile("soubor")
if (text = "a")
   text2 = readFile("xxx")
else
   text2 = readFile("yyy");
udelejNeco(text2);
# vs.

readFile("soubor", text -> if (text == "a") readFile("xxx", text2 -> udelejNeco(text2)) else readFile("yyy", text2 -> udelejNeco(text2)))

# vs. to same jako priklad 1, akorat s async await
Co je na příkladu 1 "zvýšená komplexita"? Naopak, takhle by měl vypadat všechen kód. Celý async await je snaha, se k tomuhle dostat, ale ve výsledků to prostě není pořádně composable (https://github.com/tc39/ecmascript-asyncawait/issues/7). Je to stejně blbě composable jako generátory třeba i v pythonu. Dobře to má udělaný Purescript v Aff monadu, jenomže to asi do vanilla JS jde propašovat dost těžko.

Awaitovat můžete jen uvnitř async funkce. Composable to je. Můžete awaitovat vše co vrací promise, tedy i jiné async funkce. Tomu tazateli by stačilo místo forEach použít obyčejný for.

Pythonovské generátory jsou composable. Co jiného dělá yield from?

Dokonce můžete kombinovat generátory s async await a vytvářet async generátory. V Go podobné věci zdaleka tak elegantně zapsat nejdou.

Re:Node.js a multiplexed IO obecně
« Odpověď #34 kdy: 23. 04. 2017, 16:15:46 »
V JS máte jistotu, že posloupnost operací přistupující ke sdíleným prostředkům proběhne bez přerušení. V Go tu jistotu nemáte.
A ani ji nepotřebuje - což je přesně to, o co jde, proč to má Go udělané dobře :) Komponenty nemají nic sdílet, pokud to není opravdu nezbytně nevyhnutelně nutné.

reklama


gll

Re:Node.js a multiplexed IO obecně
« Odpověď #35 kdy: 23. 04. 2017, 20:46:09 »
V JS máte jistotu, že posloupnost operací přistupující ke sdíleným prostředkům proběhne bez přerušení. V Go tu jistotu nemáte.
A ani ji nepotřebuje - což je přesně to, o co jde, proč to má Go udělané dobře :) Komponenty nemají nic sdílet, pokud to není opravdu nezbytně nevyhnutelně nutné.

Proč potom existují tooly jako tento?

https://blog.golang.org/race-detector

Re:Node.js a multiplexed IO obecně
« Odpověď #36 kdy: 23. 04. 2017, 20:59:48 »
Proč potom existují tooly jako tento?

https://blog.golang.org/race-detector
A proč ne?

andy

Re:Node.js a multiplexed IO obecně
« Odpověď #37 kdy: 23. 04. 2017, 21:06:16 »
V JS máte jistotu, že posloupnost operací přistupující ke sdíleným prostředkům proběhne bez přerušení. V Go tu jistotu nemáte.
Ale to přece není otázka blocking/non-blocking, ale důsledek toho, že JS nemá žádnou podporu pro multithreading (i user-level). Ale dobrá reklama na JS: je to super-jazyk, nemusíte řešit zámky, protože to neumí multithreading a rozhodně mezi 2 příkazy vám "omylem" nic nevleze, protože kód "po" tom prvním příkazu musíte dát jako callback a tím pádem je vidět, že tam něco vleze. Ale blbě se s tím programovalo, takže jsme vynalezli "async await", který způsobí, že vám mezi ty 2 příkazy něco klidně může vlízt a tím pádem se to chová jako ty všechny ostatní jazyky, ale jinak je to fakt lepší....

Citace
Awaitovat můžete jen uvnitř async funkce. Composable to je. Můžete awaitovat vše co vrací promise, tedy i jiné async funkce. Tomu tazateli by stačilo místo forEach použít obyčejný for.

Pythonovské generátory jsou composable. Co jiného dělá yield from?
Vida, vývoj pythonu už delší dobu nesleduju, to tam tehdy nebylo :) Ovšem bez "yield from" to taky bylo composable, stačilo použít for...yield... to je v podstatě další syntaktický cukr, podobně jako async await. Prostě to není composable ale nějak to syntaxí přiohnem, aby se aspoň ty nejčastějc používané věci dali rozumně použít a člověk se přitom neškrábal nohou za uchem.

Ale jo, ty jazyky se postupně zlepšují. Ještě pár desítek let a budou všechny docela použitelné....

Citace
Dokonce můžete kombinovat generátory s async await a vytvářet async generátory. V Go podobné věci zdaleka tak elegantně zapsat nejdou.
Protože je (často) prostě zapsat nepotřebuju. Celý async-await je prostě automaticky zapnutý....

Boo

Re:Node.js a multiplexed IO obecně
« Odpověď #38 kdy: 24. 04. 2017, 14:06:27 »
Má nějakou zvláštní výhodu node.js? Chápu princip epoll (a podobných technologií na jiných OS), ale není mi jasné, proč do toho pletou JS. Proč nepoužít C, C++ nebo třeba Rust či jiný podobný nativně kompilovaný jazyk? Ono i v Javě už jsou lambda výrazy a Java má oproti JS řadu výhod.

1. Puvodni JS neumel filesystem IO, node je proste evoluce a pridali tam moznost pouzivat systemove knihovny aby IO nemuseli vymyslet od piky. BFU receno dohackovali tam linkovani .so :)
2. Nekompilovany jazyk je zamer, proste se na to divej stejne jako na perl, python, php...
3. JS na serveru ma vyhodu napr. v tom, ze muzes stejnou knihovnu pouzit jak na frontendu v browseru tak na backendu na servru. Napr. takova validace dat v html formulari. Checknes to na forntendu, a pak jeste jednou na backendu (kvuli moznym hackum abotum co se pchaji primo na API) tou samou knihovnou. Kdybys mel na backendu treba Javu tak musis ty validatory prepsat z JS do Javy a stav se ze chybka se vloudi a nbudou validovat stejne..
4. Rychlost http servru v node - je default nenoblocking, async atd.

zboj

  • *****
  • 1 507
    • Zobrazit profil
    • E-mail
Re:Node.js a multiplexed IO obecně
« Odpověď #39 kdy: 24. 04. 2017, 14:41:33 »
V JS máte jistotu, že posloupnost operací přistupující ke sdíleným prostředkům proběhne bez přerušení. V Go tu jistotu nemáte.
Ale to přece není otázka blocking/non-blocking, ale důsledek toho, že JS nemá žádnou podporu pro multithreading (i user-level). Ale dobrá reklama na JS: je to super-jazyk, nemusíte řešit zámky, protože to neumí multithreading a rozhodně mezi 2 příkazy vám "omylem" nic nevleze, protože kód "po" tom prvním příkazu musíte dát jako callback a tím pádem je vidět, že tam něco vleze. Ale blbě se s tím programovalo, takže jsme vynalezli "async await", který způsobí, že vám mezi ty 2 příkazy něco klidně může vlízt a tím pádem se to chová jako ty všechny ostatní jazyky, ale jinak je to fakt lepší....

Citace
Awaitovat můžete jen uvnitř async funkce. Composable to je. Můžete awaitovat vše co vrací promise, tedy i jiné async funkce. Tomu tazateli by stačilo místo forEach použít obyčejný for.

Pythonovské generátory jsou composable. Co jiného dělá yield from?
Vida, vývoj pythonu už delší dobu nesleduju, to tam tehdy nebylo :) Ovšem bez "yield from" to taky bylo composable, stačilo použít for...yield... to je v podstatě další syntaktický cukr, podobně jako async await. Prostě to není composable ale nějak to syntaxí přiohnem, aby se aspoň ty nejčastějc používané věci dali rozumně použít a člověk se přitom neškrábal nohou za uchem.

Ale jo, ty jazyky se postupně zlepšují. Ještě pár desítek let a budou všechny docela použitelné....

Citace
Dokonce můžete kombinovat generátory s async await a vytvářet async generátory. V Go podobné věci zdaleka tak elegantně zapsat nejdou.
Protože je (často) prostě zapsat nepotřebuju. Celý async-await je prostě automaticky zapnutý....
Ono celé slavné async/await je jen mnoho povyku pro nic, je to nic nepřinášející zhnusnění kódu. Čistě formálně je to jen zbytečně složitě vyjádřená monáda.

gll

Re:Node.js a multiplexed IO obecně
« Odpověď #40 kdy: 24. 04. 2017, 16:24:05 »
Ono celé slavné async/await je jen mnoho povyku pro nic, je to nic nepřinášející zhnusnění kódu. Čistě formálně je to jen zbytečně složitě vyjádřená monáda.

Nemohl bys uvést ukázku pěkného kódu, který se tím zhnusí? Jak vypadá jednoduše vyjádřená monáda?

andy

Re:Node.js a multiplexed IO obecně
« Odpověď #41 kdy: 24. 04. 2017, 23:22:32 »
Ono celé slavné async/await je jen mnoho povyku pro nic, je to nic nepřinášející zhnusnění kódu. Čistě formálně je to jen zbytečně složitě vyjádřená monáda.
Nemohl bys uvést ukázku pěkného kódu, který se tím zhnusí? Jak vypadá jednoduše vyjádřená monáda?
Tak když vezmu Purescript Aff monad, což je v podstatě přesně to, co řeší async-await.

Tak když vezmu ty příklady - ten originál z té stránky:

Kód: [Vybrat]
All getJSON operations will happen in parallel, and the application will wait until all requests are complete before adding them all to the page at once.

(await Promise.all(urls.map(getJSON))).forEach(j => addToPage(j.html));
-- vs.
parTraverse getJSON urls >>= traverse (addToPage _.html)

Kód: [Vybrat]
All getJSON operations will happen in parallel, and each object will be added to the page as it arrives (possibly out of order).

await Promise.all(urls.map(getJSON).map(async j => addToPage((await j).html)));
-- vs.
parTraverse_ (getJSON >=> addToPage (_.html)) urls

Kód: [Vybrat]
All getJSON operations will happen in parallel, with the results being added to the page sequentially as they come in.

for (let j of urls.map(getJSON)) {
    addToPage((await j).html);
}

A tady tohle standardně nejde, protože to je imperativní kód, nicméně když si definujeme malé funkce...
Kód: [Vybrat]
async f = do
  v <- makeVar
  forkAff (f >>= putVar v)
  pure v
await = takeVar
Take ten kód můžeme napsat:
Kód: [Vybrat]
parTraverse (\url -> async (getJSON url)) urls >>= traverse_ (\promise -> await promise >>= addToPage _.html)
(nebo zkráceně)
parTraverse (async <<< getJSON) urls >>= traverse_ (await promise >=> addToPage _.html)
A ta sranda je, že parTraverse je jenom normální funkce, která někde volá "traverse" (obdoba forEach), takže funguje se všemi strukturami, které podporují Traversable. A na implementaci "async" a "await" (který je navíc potřeba jen, když nepoužíváme sekvenční kód) není potřeba modifikovat jazyk, ale dají se normálně naprogramovat...

gll

Re:Node.js a multiplexed IO obecně
« Odpověď #42 kdy: 25. 04. 2017, 11:34:20 »
Kód: [Vybrat]
All getJSON operations will happen in parallel, and each object will be added to the page as it arrives (possibly out of order).

await Promise.all(urls.map(getJSON).map(async j => addToPage((await j).html)));
-- vs.
parTraverse_ (getJSON >=> addToPage (_.html)) urls

Tohle není úloha, kde by použití await vyniklo. Await se hodí hlavně tam, kde byste jinak řetězil několik then.

S bluebirdem bych to zapsal asi takto:

Kód: [Vybrat]
Promise.map(urls, getJSON).each(j => addToPage(j.html));

Je to stejně dlouhé jako vaše řešení v purescriptu.

V JS máte jistotu, že posloupnost operací přistupující ke sdíleným prostředkům proběhne bez přerušení. V Go tu jistotu nemáte.
Ale to přece není otázka blocking/non-blocking, ale důsledek toho, že JS nemá žádnou podporu pro multithreading (i user-level). Ale dobrá reklama na JS: je to super-jazyk, nemusíte řešit zámky, protože to neumí multithreading a rozhodně mezi 2 příkazy vám "omylem" nic nevleze, protože kód "po" tom prvním příkazu musíte dát jako callback a tím pádem je vidět, že tam něco vleze. Ale blbě se s tím programovalo, takže jsme vynalezli "async await", který způsobí, že vám mezi ty 2 příkazy něco klidně může vlízt a tím pádem se to chová jako ty všechny ostatní jazyky, ale jinak je to fakt lepší....

to se týká pouze IO operací. Posloupnosti ne-IO operací jsou v JS zcela bezpečné, v Go musíte řešit zámky.

andy

Re:Node.js a multiplexed IO obecně
« Odpověď #43 kdy: 25. 04. 2017, 12:56:25 »
Kód: [Vybrat]
All getJSON operations will happen in parallel, and each object will be added to the page as it arrives (possibly out of order).

await Promise.all(urls.map(getJSON).map(async j => addToPage((await j).html)));
-- vs.
parTraverse_ (getJSON >=> addToPage (_.html)) urls

Tohle není úloha, kde by použití await vyniklo. Await se hodí hlavně tam, kde byste jinak řetězil několik then.
No jo, ale to pak vypadá jako:
Kód: [Vybrat]
funkce = do
  r <- zavolejAjax
  b <- zobrazUzivateliDialogAPockejAzKlikneNaOK r
  zavolejJinyAjax b
což je docela primitivní záležitost, se kterou se moc nemusí přemýšlet :) Tohle byl aspoň trošku challenge, jak to napsat (obzvlášť to poslední...)

Citace
to se týká pouze IO operací. Posloupnosti ne-IO operací jsou v JS zcela bezpečné, v Go musíte řešit zámky.
Jo, takhle se před 20 lety implementoval kooperativní multitasking. Go je přece jen trošku novější....

Re:Node.js a multiplexed IO obecně
« Odpověď #44 kdy: 25. 04. 2017, 21:03:27 »
S bluebirdem bych to zapsal asi takto:

Kód: [Vybrat]
Promise.map(urls, getJSON).each(j => addToPage(j.html));

Je to stejně dlouhé jako vaše řešení v purescriptu.
...což bude nejspíš tím, že Promise je instance monády, akorát se to nesmí říkat, aby to javascriptaře neděsilo ;)

 

reklama