czemu 1000 wątków przy 500 requestach?

0

Oglądam

i tam jest że przy synchronicznym podejściu dla N requestów będzie 2 x N nudzących się wątków?

Moja intuicja mi podpowiadała że będzie N nudzących się wątków i nie mogę tego rozkminić.

4

To oglądasz coś co jest już przestarzałe.

Od JVM 21 weszło na pełnym gazie: project Loom aka Virtual Threads. Oficjalnie już wspierane przez najnowszy Spring Boot (choć inne liby się ociągają).

Do zastosowań produkcyjnych nadaje się ale na razie tylko tam gdzie nie ma wielowątkowości (pojawił się pewien problem z synchronized keyword). Niemniej w kolejnym wydaniu zapewne poprawią.

Całość polega na tym że kod jest transparentny, czyli kod sync i async wygląda uwaga uwaga tak samo! To jest nowa jakość i spora ulga dla programistów którzy w innych językach muszą klepać co linijkę święte słowa async await i amen.

Oficjalnie więc ogłaszam Kotlin Coroutines are dead in 2024. RIP

0
0xmarcin napisał(a):

Całość polega na tym że kod jest transparentny, czyli kod sync i async wygląda uwaga uwaga tak samo! To jest nowa jakość i spora ulga dla programistów którzy w innych językach muszą klepać co linijkę święte słowa async await i amen.

Czyli w końcu Java stała się w pełni funkcyjna i ostatni argument za forsowaniem Scali na produkcji odpadnie?

1
loza_prowizoryczna napisał(a):
0xmarcin napisał(a):

Całość polega na tym że kod jest transparentny, czyli kod sync i async wygląda uwaga uwaga tak samo! To jest nowa jakość i spora ulga dla programistów którzy w innych językach muszą klepać co linijkę święte słowa async await i amen.

Czyli w końcu Java stała się w pełni funkcyjna i ostatni argument za forsowaniem Scali na produkcji odpadnie?

W Scali mówią na to Direct Style. Ale mi się nie podoba. Mam opinię iż to wszystko jest dla programistów którzy nie potrafia używać monad :P
BTW Scala (A w zasadzie biblioteka Cats) ma też własną implementację Fibers, ale nie są one używane bezpośrednio tylko są podstawą do implementacji monad efektów jak IO

BTW2 Tak jak pisze @0xmarcin Direct Style nie ma nic wspólnego z byciem funkcyjnym, oni w zasadzie z byciem obiektowym. To znaczy iż jest nowa płaszczyzna do kłótni Direct Style vs async await i suspend (Kotlin) vs Future (Scala) i Promise (JS) i IO (Scala, Haskell)

0

No koledzy dzięki za oftop, ale może ktoś odpowie jednak na pytanie.

Dla ułatwienia dodam że fragment o który pytam jest totalnie language agnostic więc nie ograniczajcie się do Java a tym bardziej jakiejś konkretnej jej wersji.

3

@marian pazdzioch w tym filmie z yt, masz przykład 500 RPS i 500 wątków, z czego każdy wątek przy obsłudze requestu woła zewnętrzny komponent (dysk/sieć etc.) i to trwa 2sekundy. W efekcie, przy synchronicznym przetwarzaniu masz : 1 request / 2 sekundy per wątek (0.5 requestu / sekundę per wątek). Przy 500 wątkach masz 500 watków * 0.5 request / sekundę per wątek = 250 requestów / sekundę. System jest w stanie ogarnąć 250 requestów / sekundę na 500 wątkach, a napływa 500 requestów na sekundę.

Przy 1000 wątków i synchronicznym przetwarzaniau masz: 1000 wątków * 0.5 request / sekundę per wątek = 500 request / sekundę.

Dla podanego przykładu, przy 500 wątkach i 500 RPS można by próbować zmniejszać czas I/O przez cachowanie, czy dystrybucję na większą ilość dysków, czy szybsze dyski, dedykowane pod workload kanały komunikacji itp. Dzięki temu zmniejszyć czas przetwarzania z 2sek do 100ms (0.1s) (np. przez przejście z dysków obrotowych na SSD). Wówczas przy synchronicznym przetwarzaniu miałbyś 1 request / 0.1 s per wątek => 10 request / sek per wątek. 50 wątków dałoby radę ogarnąć workload 500 RPS.

Do tego typu kalkulacji masz aparat matematyczny (procesy stochastyczne, teoria kolejek), który może być użyty do wyliczenia ile potrzebujesz wątków. Jaki napływ requestów system jest w stanie unieść, ile średni będzie requestów w kolejce, jak długo średnio będą czekać na obsługę itd.

4
marian pazdzioch napisał(a):

i tam jest że przy synchronicznym podejściu dla N requestów będzie 2 x N nudzących się wątków?

Moja intuicja mi podpowiadała że będzie N nudzących się wątków i nie mogę tego rozkminić.

Tylko, że on tam nie mówi o N requestów i 2xN nudzących się wątkach.

Masz 500 requestów na sekundę.
Kazdy request jest blokowany na 2 sekundy (przy wołaniu do zewnętrznej zależności).
Więc w pewnym momencie będzie 1000 aktywnych wątków zablokowanych. Jakby blokowane były na 3 sekundy to byłobo 1500.

np. gdbyby idealnie co sekunda przychodziło naraz 500 żądań to miałbyś w pewnym momencie:

  • te nowo powstałe 500 wątków, które będzie czekać 2 sekundy,
  • 500 wątków, które będzie czekać jeszcze 1 sekundę (z poprzedniego rzutu).
1

Nie zgadzam się z 2 ostatnimi odpowiedziami. Bardziej na produkcji stosuje się setup gdzie liczba wątków dla serwera jest ustalona "na sztywno" np. 500.
Requesty które przyjdą później będą skolejkowane (priomo - pamięć dla wątków jest przypisana na stale; secondo - to taki prymitywny throttling; trecio - ochrona przed DoS).

Jeżeli ktoś chce sprawdzić faktycznie a nie opierać się na jakimś slajdzie to powinien odpalić jakąś apkę http i potraktować jmeterem lub https://github.com/grafana/k6 i wtedy zobaczy w jconsole czy JFR co tam faktycznie się dzieje.

@marian pazdzioch zamiast pytać tutaj, mógł to już dawno empirycznie sprawdzić na własnym stacku i używając takiej konfiguracji z jaką pracuje.

1
0xmarcin napisał(a):

Nie zgadzam się z 2 ostatnimi odpowiedziami. Bardziej na produkcji stosuje się setup gdzie liczba wątków dla serwera jest ustalona "na sztywno" np. 500.
Requesty które przyjdą później będą skolejkowane (priomo - pamięć dla wątków jest przypisana na stale; secondo - to taki prymitywny throttling; trecio - ochrona przed DoS).

Jeżeli ktoś chce sprawdzić faktycznie a nie opierać się na jakimś slajdzie to powinien odpalić jakąś apkę http i potraktować jmeterem lub https://github.com/grafana/k6 i wtedy zobaczy w jconsole czy JFR co tam faktycznie się dzieje.

Nie, stosuje się różnie. Stare/klasyczne aplikacje oparte o blokujące wątki odpala sie tak jak piszesz.
Nieblokujące aplikacje odpala się na minimalnej liczbie wątków (2 razy liczba core na przykład - inaczej zabawa w non blocking nie bardzo ma sens).

Wszystko zależy od technologii w jakiej apka jest zrobiona.
W javowych frameworkach nadal rządzi blokowanie, ale część (netty, spring Web-Flux) jest robiona nieblokująco. W kotlinie i scali używa się nieblokujących serwerów częściej.
W JS/TS to nawet za bardzo nie ma wyjścia - wszystko robi się non blocking (minimalna liczba wątków).

1
0xmarcin napisał(a):

Nie zgadzam się z 2 ostatnimi odpowiedziami.

A z czym konkretnie się nie zgadzasz? Kolega zapytał skąd te 1k wątków dla synchronicznego przetwarzania ruchu o natężeniu 500 RPS. Wyjaśnienie jest nieadekwatne?

1 użytkowników online, w tym zalogowanych: 0, gości: 1