Jak v Javě udělat thread s návratovou hodnotou?

anonym

Re:Jak v Javě udělat thread s návratovou hodnotou?
« Odpověď #15 kdy: 08. 07. 2018, 11:46:53 »
Je pravda.

Když máš webovou službu, tak tam může v 1 okamžik klidně být 1000 requestů naráz, tzn. 1000 threadů naráz. Tak nějak si to musí ten systém pošéfovat. Hoši, běžte si počítat ty vaše Fibonaciho posloupnosti jinam, tady se řeší Java a pořádné systémy  8)
Jestli trollíš a snažíš se hrát prasiče, tak ti to celkem jde.

Jak je třeba obsluhovat spoustu požadavků zároveň tak je dost blbé spouštět hromady vláken. Pro čekání na IO nepotřebuju hromady alokované paměti pro zásobník a další blbiny. Každý relativně moderní OS a jen trochu příčetný framework (včetně Javy) podporují asynchronní IO.

Z těch 1000 requestů v každém okamžiku většina čeká (na disk, síť, ...). Na to nepotřebuje vlákno.

To je tu furt jak u blbých. Ano, když obsluhuješ 1000 requestů naráz, nebudeš paralelizovat flow, protože je to zbytečné a nic to nezrychlí. Čti pořádně co píšu, já jsem reagoval na to, jak tu někdo psal, že 1000 vláken je moc velká zátěž.

Pokud mám interní inf. systém, kde je maximálně třeba 5 požadavků naráz, tak můžu urychlit blokující operace tím, že vytvořím další vlákna, a těch ať si je dohromady klidně 1000. Kapišto?


anonym

Re:Jak v Javě udělat thread s návratovou hodnotou?
« Odpověď #16 kdy: 08. 07. 2018, 11:52:39 »
Ano, když budeš počítat ovečky v 1000 vláknech naráz a máš jen 4 jádra, jsi blbec na tisícátou. Ale když těch 1000 vláken je kvůli provedení blokujících operací, které můžou trvat každá třeba 500ms, tak je to OK. Ano, je tam navíc zátěž kvůli těm vláknům samotným, ale ne taková, aby to vyvážilo blokující operaci o délce trvání třeba 50ms za každou.

Rozumíte nebo je to moc těžké na pochopení?

Takže, klasický interní informační systém, který používá tak 10 lidí naráz, může klidně mít paralelizované flow pro blokující operace, NE PRO RYCHLOST VÝPOČTU. Pro říkám, ať si jdete počítat fibonaciho posloupnosti (akademicti teoretici) někam jinam, protože tohle je praxe.

kraxna

Re:Jak v Javě udělat thread s návratovou hodnotou?
« Odpověď #17 kdy: 08. 07. 2018, 11:58:00 »
Ano, když budeš počítat ovečky v 1000 vláknech naráz a máš jen 4 jádra, jsi blbec na tisícátou. Ale když těch 1000 vláken je kvůli provedení blokujících operací, které můžou trvat každá třeba 500ms, tak je to OK. Ano, je tam navíc zátěž kvůli těm vláknům samotným, ale ne taková, aby to vyvážilo blokující operaci o délce trvání třeba 50ms za každou.

Rozumíte nebo je to moc těžké na pochopení?

Takže, klasický interní informační systém, který používá tak 10 lidí naráz, může klidně mít paralelizované flow pro blokující operace, NE PRO RYCHLOST VÝPOČTU. Pro říkám, ať si jdete počítat fibonaciho posloupnosti (akademicti teoretici) někam jinam, protože tohle je praxe.

A nebo to udelas poradne, misto threadu pro blokujici operace to udelas reaktivni, coz zpusobi, ze to bude jeste rychlejsi, potrebovat mene pameti, nebude to zatezovat OS a ty vlakna pak muzes na neco efektivnejsiho, napr. kdyz potrebujes skutecne neco, co bezi paralelne :-)

Trosku jsi s timhle pristupem zaspal dobu, takhle se veci delaly 10 let zpatky.

anonym

Re:Jak v Javě udělat thread s návratovou hodnotou?
« Odpověď #18 kdy: 08. 07. 2018, 12:01:07 »
Ano, když budeš počítat ovečky v 1000 vláknech naráz a máš jen 4 jádra, jsi blbec na tisícátou. Ale když těch 1000 vláken je kvůli provedení blokujících operací, které můžou trvat každá třeba 500ms, tak je to OK. Ano, je tam navíc zátěž kvůli těm vláknům samotným, ale ne taková, aby to vyvážilo blokující operaci o délce trvání třeba 50ms za každou.

Rozumíte nebo je to moc těžké na pochopení?

Takže, klasický interní informační systém, který používá tak 10 lidí naráz, může klidně mít paralelizované flow pro blokující operace, NE PRO RYCHLOST VÝPOČTU. Pro říkám, ať si jdete počítat fibonaciho posloupnosti (akademicti teoretici) někam jinam, protože tohle je praxe.

A nebo to udelas poradne, misto threadu pro blokujici operace to udelas reaktivni, coz zpusobi, ze to bude jeste rychlejsi, potrebovat mene pameti, nebude to zatezovat OS a ty vlakna pak muzes na neco efektivnejsiho, napr. kdyz potrebujes skutecne neco, co bezi paralelne :-)

Trosku jsi s timhle pristupem zaspal dobu, takhle se veci delaly 10 let zpatky.

Omg, reaktivní architekturu si dělejte u těch vašich javascriptových sraček. Přístup, který já zmiňuju, se nedělal před 10 lety, dělal se už před 50 lety a bude se dělat pořád. Reaktivní programování se používá u webového UI a je to výsledek objevování kola, webolepiči.

anonym

Re:Jak v Javě udělat thread s návratovou hodnotou?
« Odpověď #19 kdy: 08. 07. 2018, 12:02:35 »
Bych chtěl vidět jak by jsi složitou bankovní business logiku udělal reaktivně a potom to debugoval, to by se ti protáčely panenky.


anonym

Re:Jak v Javě udělat thread s návratovou hodnotou?
« Odpověď #20 kdy: 08. 07. 2018, 12:12:55 »
A v Javě se to "reaktivní programování" používá dávno, už od dob Swingu. Taky C++ Qt používá v podstatě "reaktivní programování", je to dokonce přímo vsazeno do toho frameworku. Všude kde je UI se používalo "reaktivní programování" snad vždy. Pointa této filozofie je možná taková, že když máš UI a chceš ho udělat responsivní, aby uživatel na každou akci viděl reakci, tak použiješ události. Není to nic nového, to si uvědom, to jenom vy z javascriptu co lepíte webovky si a děláte to dokolečka dokola si myslíte, že to je celý svět.

Ono, nakonec, můj přístup je reaktivní programování taky. Ale flow mezi kliknutím na buttonek a zobrazením výsledku je obrovské, složité a dlouho trvá.

anonym

Re:Jak v Javě udělat thread s návratovou hodnotou?
« Odpověď #21 kdy: 08. 07. 2018, 12:18:44 »
Ono v plnotučném javoském backendu se událostmi řízené programování používá taky, ale jen tam, kde je potřeba. Je to jen jedno paradigma vhodné na určitý usecase. Lidi co dělají UI kdežto používají snad jenom toto paradigma, ale Javista musí umět dělat obojí.

Jsi mě naštval, protože jsem se jednou octl mezi javascriptářema, kteří pořád kydali ohledně reaktivního programování a na mě se dívali jak na nějakého dinosaura. A mě bylo zatěžko jim říct, že o tom vlastně vědí hovno a že to je paradigma vhodné na jejich usecase.

Taky pořád prudili s funkcionálním programováním, to mě taky štvalo. Že já jsem dinosaurus co dělá ještě to OOP v Javě. A mě bylo zatěžko jim říct, že v tom svém funkcionálním programování budou, v jejich případě, dělat stejné nečitelné hovna, jako by byli dělali v OOP, protože psát pěkný kód se dá v ledacčem.

No nic.

borekz

  • ****
  • 494
    • Zobrazit profil
    • E-mail
Re:Jak v Javě udělat thread s návratovou hodnotou?
« Odpověď #22 kdy: 08. 07. 2018, 13:08:17 »
Každé vlákno musí byť spustené, aby zistilo, či môže pokračovať, a keď je ich 10, tak to je akceptovateľné, ale ak ich je 1000 a je tam slabé CPU, tak to výrazne spomaľuje beh.
Tak máš hodně špatný operační systém. V normálním systému je zátěž CPU vlákna čekající na událost zcela zanedbatelná. Co není zanedbatelné, je spotřeba paměti a to je skutečný důvod, proč se např. na webserveru Nginx používá epoll místo vláken.

Něco jiného je, když to vlákno skutečně něco dělá. Potom je asi celkově rychlejší úlohy spouštět postupně nebo jen podle počtu CPU. Tu zátěž CPU nezpůsobuje "zjišťování, zda může pokračovat", ale ukládání stavu CPU a přepisování cache.

.

Re:Jak v Javě udělat thread s návratovou hodnotou?
« Odpověď #23 kdy: 08. 07. 2018, 13:21:22 »
Tzn. já si z něj můžu vzít jen určitý počet vláken? Z toho mi ale hrozí deadlock, ne? Proč tam prostě není nekonečný počet vláken?

Protoze neni efektivni napr. na 2 jadru spustit 100 vlaken :-) Pokud ti hrozi deadlock, tak to mas spatne navrzene.
Myslenka future a dalsich je takova, ze se jedna o nezavisle vypocty, ktere postupne chceme ziskat - tzn. neco jako deadlock by tu vubec nemelo mit moznost nastat.

Samozrejme si muzes udelat i vlastni threadpool, ale stejne to zavani spatnym navrhem.
A to jste vzal kde? Pokud se bavíme o zelených vláknech, tak je to efektivní i v řádu tisíců a ani řády desetitisíců nejsou nějak kor moc neefektivní. Na tomhle je postaveno např. Go a v těchto typech úloh drtí Javu celkem s přehledem jak ve zdrojích, tak v celkovém výkonu.

kraxna

Re:Jak v Javě udělat thread s návratovou hodnotou?
« Odpověď #24 kdy: 08. 07. 2018, 13:42:53 »
A to jste vzal kde? Pokud se bavíme o zelených vláknech, tak je to efektivní i v řádu tisíců a ani řády desetitisíců nejsou nějak kor moc neefektivní. Na tomhle je postaveno např. Go a v těchto typech úloh drtí Javu celkem s přehledem jak ve zdrojích, tak v celkovém výkonu.

Bavime se  tu celou dobu o Jave, kde vlaknovy model je 1:1 a tudiz to efektivni neni. Java vlakno = OS vlakno. Go pouziva Coroutine.

V Jave pro podobny model existuje spousta moznosti tez - pocinaje CompletableFuture pres Reactive Streams / RxJava / Reactor, konce necim jako je Quasar, ktery by se mel v praci Project Loom dostat primo do JDK :-)

echt

Re:Jak v Javě udělat thread s návratovou hodnotou?
« Odpověď #25 kdy: 08. 07. 2018, 14:27:26 »
Každé vlákno musí byť spustené, aby zistilo, či môže pokračovať, a keď je ich 10, tak to je akceptovateľné, ale ak ich je 1000 a je tam slabé CPU, tak to výrazne spomaľuje beh.
Tak máš hodně špatný operační systém. V normálním systému je zátěž CPU vlákna čekající na událost zcela zanedbatelná. Co není zanedbatelné, je spotřeba paměti a to je skutečný důvod, proč se např. na webserveru Nginx používá epoll místo vláken.

Něco jiného je, když to vlákno skutečně něco dělá. Potom je asi celkově rychlejší úlohy spouštět postupně nebo jen podle počtu CPU. Tu zátěž CPU nezpůsobuje "zjišťování, zda může pokračovat", ale ukládání stavu CPU a přepisování cache.

Vychádzam z toho, že pri každom prepínaní vlákna sa musí prehodiť stack (registre) a v prípade event-u je to v nejakom pool-e, ktoré má svoj stack nezávislý od zaregistrovaných udalostí.

Vychádzam z dokumentácie, ktorú zverejnil MS ohľadom správania sa vlákien nad IO operáciami, ale je to dosť starý článok (odkaz nemám). Pekne tam popisovali dopad výkonu pri IO operáciach v porovnaní s udalosťami.

Z aplikačného pohľadu je ten výkonnostný dopad marginálny, s tým súhlasím. Ale programoval som aj embedd (Windows Embedd CE), kde hodiť vlákno nad každú prkotinu s IO je dosť ťažký údel na HW úrovni. Fakticky to záleží od prípadu užitia, ale vlákna so sebou ťahajú dosť veľa batožiny. Osobne pochybujem, že toto nejako magicky ošetrili v ostatných OS.

Pokiaľ viem Linux (rok 2000+ tuším) tiež trpel týmto problémom, keď priorizoval operácie a namiesto toho použili podobný trik, ale ešte nie na úrovni udalostí a to, že hodili do skupín úlohy s podobnou prioritou a jednoducho ich spustili namiesto toho, aby kontrolovali, kto má prednosť.

kraxna

Re:Jak v Javě udělat thread s návratovou hodnotou?
« Odpověď #26 kdy: 08. 07. 2018, 14:46:03 »
Z aplikačného pohľadu je ten výkonnostný dopad marginálny, s tým súhlasím. Ale programoval som aj embedd (Windows Embedd CE), kde hodiť vlákno nad každú prkotinu s IO je dosť ťažký údel na HW úrovni. Fakticky to záleží od prípadu užitia, ale vlákna so sebou ťahajú dosť veľa batožiny. Osobne pochybujem, že toto nejako magicky ošetrili v ostatných OS.

Dopad neni marginalni. V praci jsme vyvijeli napr. daemon, ktery paralelne procesuje statistice konkurentnich TCP spojeni, epoll se v takovem pripade rozhodne neprobouzi s jednou udalosti na jednom socketu.

V opacnem pripade, i kdybysme zanedbali pametovou narocnost, tak nepouzit epoll (ale misto toho blokujici vlakna) by znamenalo misto jednoho vlakna probrat vetsi mnozstvi vlaken - tudiz vyrazne vetsi CPU zatez a rezii.

echt

Re:Jak v Javě udělat thread s návratovou hodnotou?
« Odpověď #27 kdy: 08. 07. 2018, 14:57:11 »
Dopad neni marginalni. V praci jsme vyvijeli napr. daemon, ktery paralelne procesuje statistice konkurentnich TCP spojeni, epoll se v takovem pripade rozhodne neprobouzi s jednou udalosti na jednom socketu.

V opacnem pripade, i kdybysme zanedbali pametovou narocnost, tak nepouzit epoll (ale misto toho blokujici vlakna) by znamenalo misto jednoho vlakna probrat vetsi mnozstvi vlaken - tudiz vyrazne vetsi CPU zatez a rezii.

Bezpodmienečne súhlasím. Skôr apelujem na borekz s jeho vyhlásením, že to je v poriadku. Z pohľadu OS a HW sa deje presne toto, vysoká záťaž CPU a pamäte, lebo sa musí prehadzovať existujúci a čakajúci stack na HW vlákno. V aplikácií sa ale vykoná minimum inštrukcií a výkonnostný dopad je v tejto časti takmer žiadny, všetko si odnesie OS a HW.

kraxna

Re:Jak v Javě udělat thread s návratovou hodnotou?
« Odpověď #28 kdy: 08. 07. 2018, 15:12:20 »
Bezpodmienečne súhlasím. Skôr apelujem na borekz s jeho vyhlásením, že to je v poriadku. Z pohľadu OS a HW sa deje presne toto, vysoká záťaž CPU a pamäte, lebo sa musí prehadzovať existujúci a čakajúci stack na HW vlákno. V aplikácií sa ale vykoná minimum inštrukcií a výkonnostný dopad je v tejto časti takmer žiadny, všetko si odnesie OS a HW.

To jsem te asi nepochopil - to, ze aplikace zpracuje jen zlomek RPS pri pouziti blokujicich vlaken oproti pouziti udalostnich / reaktivnich mechanismu, me totiz prislo jako docela velky aplikacni dopad :-)

anonym

Re:Jak v Javě udělat thread s návratovou hodnotou?
« Odpověď #29 kdy: 08. 07. 2018, 15:24:31 »
Takže, našel jsem asi nejlepší způsob jak dělat asynchronní kód ve Springu:

https://spring.io/guides/gs/async-method/

Stačí anotovat async metody jako @Async, o zbytek se postará Spring.
Kód: [Vybrat]
@Service
public class GitHubLookupService {

    private static final Logger logger = LoggerFactory.getLogger(GitHubLookupService.class);

    private final RestTemplate restTemplate;

    public GitHubLookupService(RestTemplateBuilder restTemplateBuilder) {
        this.restTemplate = restTemplateBuilder.build();
    }

    @Async
    public CompletableFuture<User> findUser(String user) throws InterruptedException {
        logger.info("Looking up " + user);
        String url = String.format("https://api.github.com/users/%s", user);
        User results = restTemplate.getForObject(url, User.class);
        // Artificial delay of 1s for demonstration purposes
        Thread.sleep(1000L);
        return CompletableFuture.completedFuture(results);
    }

}

Java to zase dokázala, je to asi nejlepší způsob psaní anync kódu co jsem zatím viděl.

Pokud dostane Java ten Quasar do JDK, tak ve Springu určitě přibude i možnost, aby to byly Fibery a nikoliv Thready. Možná už teď to ve Springu jde.