Transkrypcja
Temat rozmowy
Cześć, Michał!
Cześć, Wojtek!
Jaki temat na dzisiaj? Jakiś fajny?
Weźmy jakiś fajny. Może zaczniemy sobie taki temat, który pewnie trochę się też rozwinie na więcej odcinków, ale może zaczniemy o C++. Będziemy teraz, bo to jeszcze inny temat, który miejmy nadzieję skończy się na jednym odcinku szybko i konkretnie.
Szybko i konkretnie.
No dobra, niech będzie ta Java. Niech będzie, niech stracę. A właściwie Java, i czy Java wciąż jest powolna?
A nie była kiedyś właśnie? Czy w sensie, że dalej jest, czy dalej?
Tutaj zdania ekspertów są podzielone.
Czyli bardzo dobrze! I właśnie, jak z tą Javą jest? W końcu, czy ona jest szybka? Czy jest wolna? Czy było wolno, czy… czy po prostu przyspieszyła, czy może to wszystko przyspieszyło? Java jest jaka jest, tylko że skorzystała na postępie w sprzęcie, np. wydajności. To są takie teorie, że się sekunda skraca, ale musiałaby się wydłużyć. To by wtedy przyspieszyło, przyspieszyło.
Definicja wydajności
No dobra, to, ale w sensie o wydajności będziemy, o wydajności, o wydajności. To może najpierw definicja. Co to jest ta wydajność?
No co ja? No dobra, to wydajność. To by było tego z wzorem, ze wzorem. Zapomniałem jak jest wzór na wydajność, ale wydajność można by opisać jako: ile maszyna wyda, ile maszyna wyda. Czyli po prostu przy ustawieniach jakiś tam naszych, które mamy, jak dużo dobra dostarczy nam w jednostce czasu nasz grajdołek po prostu.
No właśnie, czy to zależy troszkę od tego kontekstu? Co chcą mierzyć tak naprawdę? Czy chcą mierzyć szybkość wykonania jakiegoś naszego super algorytmu, czy może chcemy mierzyć ilość użytkowników, które obsłuży nasza super aplikacja na sekundę? Więc to jest dużo pewnie kryteriów, ale zwykle jak się o Javie mówi, to pewnie tak, jak potocznie się czasami mówi, że jest taka powolna. W sensie, że ogólnie i w ogóle wszystko co z Javą jest tam związane, to albo to jest takie wolne, albo Java zamula. Odpalasz tego Eclipse’a, on tam Ci rzęzi, rzęzi i po minucie masz…
Percepcja Javy a narzędzia
Ten projekt Eclipse to tak odpalałem w 2018 pewnie, ale po co i dlaczego ja też wtedy odpalałem? No, może 19. Wtedy jeszcze był pewien projekt, pewien projekt związany z Eclipse’em musiał być. Ale właśnie pytanie, czy to właśnie taka opinia obiegowa, trochę o tej powolności właśnie, nie ma związku, że tak powiem, z otoczeniem Javy czy właśnie z różnymi narzędziami, które w Javie się używało, np. taki Eclipse. Nie wiem, ja jakoś tak Eclipse’a kojarzę z narzędziem, które które właściwie raz dziennie trzeba było restartować, żeby tam sobie przeczyściło swoje kesze czy jakieś tam inne cuda, bo inaczej to po prostu nie dało się z tego korzystać.
Jak się w nocy jeszcze dawało, to raz w nocy też.
Oraz w nocy też. Oczywiście raz w cyklu swojego kodowania. Wszystkie te takie ciężkie serwery aplikacyjne, jakiś JBoss czy nawet WebLogic. Jeszcze był z tych lżejszych. Stosowaliśmy GlassFish. To dopiero był wynalazek, który tam był. Asa zastępował też, też do przeczyszczenia raz na jakiś czas. I właśnie co? Chyba to jest ten ekosystem? Mam wrażenie, że w tamtych latach, powiedzmy kilkanaście lat temu, nie bójmy się nawet powiedzieć 20…
Nie bójmy się.
Może po… sprawiało taką, taką taką percepcję, że potrzeba wiary, bo to wszystko jest powolne, bo mi się cały czas zawiesza, bo serwery nie działają, bo coś. A jeszcze jak do tego dołożymy takie wynalazki jak Java applety wspaniałe, tutaj wspaniała technologia czy nawet Java Web Start też, który gdzieś tam odpalał różne, różne aplikacje.
Applety też jako takie dziecko tych technologii sandboxowych w przeglądarkach, trochę jak Flash, jak Silverlight, bo te technologie nigdy jakoś tam szybkością nie grzeszyły.
Oj, chyba aplety tu wpisały się. No, chyba były projektowane takie wkurzające, takie wkurzające i tak musiały tak zamulać. No właśnie. Tak się zastanawiam. To są oczywiście takie subiektywne troszkę, że tak powiem, wrażenia, bo nie mamy oczywiście żadnych twardych danych czy jakichś innych metryk na poparcie tych spostrzeżeń. Przecież pamiętam, ale pamiętam. Pamięć oczywiście zawodna.
Pewnie tak. Pamiętamy to lepiej niż było, bo przecież pamięć wypiera rzeczy negatywne i zostaje nam tylko te najlepsze. Czyli, że ten Eclipse to jednak działał trochę i jednak działał.
Swego czasu tam działał i jakoś tam dawał radę, ale wiadomo, miał swoje bolączki. I pytanie, te kilkanaście czy te 20 lat temu pewnie też sprzęt troszkę nie domagał.
Wpływ postępu sprzętowego
No właśnie miałem. Mówię, to kilkanaście lat temu to „Mach I” dopiero był.
No właśnie, to też było po Eclipse. I, który też bardzo wolno pamiętam.
No, no, może „Zmierzch” trochę i trzeba było ładować każde domostwo, zanim się do niego weszło. Takie długie ekrany ładowania, ale tak ładnie malowane, bo są ładne. Mimo to Java nie miała takich. No nie, bo tam trzeba było ładować. Każdą klasę się do niej weszło. Ale rzeczywiście. No pewnie. Pewnie. Pewnie język jako system też troszkę ucierpiał ze względu, można powiedzieć na jednak ograniczone, ograniczone moce i zasoby sprzętowe. Oczywiście można powiedzieć, że nie był też odpowiednio zoptymalizowany, żeby wykorzystać ówczesne standardy czy to pamięci operacyjnej, czy prędkości tamtejszych ówczesnych procesorów. Natomiast czy w dzisiejszych czasach coś tutaj się poprawiło?
No, coś tam się poprawiło, Eclipse już nie ma, a to poczucie stanowczo jest na obrzeżach. Ale właśnie biorąc pod uwagę ten niesamowity postęp ogólnie w sprzęcie. Czyli nawet…
Na pewno sprzęt poszedł do przodu i to zauważalnie, bo ten „pierwszy, który tam zmalał”, kiedyś dawno temu, to teraz to na jakimś kalkulatorze się pewnie odpali. A do „Wieśka III” na przykład dołożyli ostatnio takiego moda, że on faktycznie jest w stanie go stłamsić. Zaznaczę: tą maszynę, na której to chodzi przy jakichś tam odpowiednio dużych ustawieniach, ale jednak maszyny dają radę.
Czyli tą z tą dawką to też dają radę. Nie tam ta powolność versus wierność. To było takie zagadnienie. Znaczy, to były takie może nie contra, tylko połączone ocenianie, bo jak się odpaliło tego Eclipse’a, to on potrafił na takim komputerze z Windowsem, który na tych czterech gigabajtach RAM-u coś tam jeszcze zzipa zabrać 3 i koniec, i wszystko zmalało, i wchodziło sobie wirtualizację, i wtedy to już nawet nie szło kliknąć czasami. Zwłaszcza jak jakiś zaczął oczyszczać tą pamięć nieszczęsną, bo tam miał nadzieję, że coś tam jeszcze odzyska.
Teraz jak mamy np. 32 giga RAM-u w byle kalkulatorze, to też możemy sobie poszaleć. I pewnie trochę poszły technologicznie też te cacka ze stajni Javy do przodu, także tam już nawet to śmiecenie pamięci może być jakieś ciutkę lżejsze.
No tak, no właśnie tutaj głównym chyba zarzutem dla Javy od zarania jej powstania jest ta pamięć o szerokość z powodów, które gdzieś tam sobie wymienimy za chwilkę w ramach różnych inicjatyw, które mają ten problem poprawić. Ale przecież Bill mówił tam kiedyś, nie pamięta, w którym roku, że na dobrą sprawę tam chyba 640 KB SQL dostarczyć powinno wystarczyć.
No, ci goście od Javy tego nie posłuchali, jakoś zdecydowanie nie dlatego, że wtedy było to trochę lat później, ale o tyle chyba Java ewidentnie zyskała na tym postępie, chociażby w ilości RAM-u, więc spokojnie może, może już tam pochłonąć cały RAM prawie jak Chrome. No, ale nie da się. Nie da się ukryć, że to na pewno trochę dodało jej skrzydeł, żeby sobie tam mogła spokojnie te wszystkie swoje obiekty i wszystko do pamięci powrzucać.
No wiadomo, postępy w procesorach i w szybkości taśmowych coś tam, coś tam do znaczenia. No i pytanie, czy w dzisiejszych czasach, biorąc pod uwagę ten sprzęt i relatywnie jego niewielką cenę, czy jest sens w ogóle jakoś mocniej optymalizować? Bo jeśli popatrzymy na to na koszty godziny pracy człowieka, optymalnie żyjącego programisty. Porównamy to z kosztem hardware’u, czyli czy to RAM-u, czy procesora z 8 giga, czy właśnie kosztem przesunięcia tego suwaka w chmurze, to w dzisiejszych czasach jest oczywiste, że prościej jednak ten suwaczek przesunąć w prawo albo kupić sobie…
No, ale to jest prawo niższe niż to takie. Oczywiście dać mu tą godzinę optymalizować. Bo zakładając, że ktoś w godzinę rzeczywiście optymalizuje na tyle, że bardzo jakiś oficjalny nie jest gorszym, jakiś jakiś zauważalny rozgrzeje i pójdzie.
No właśnie. No właśnie, kostka RAM-u kupiona zostanie, on zostanie wysłany.
Więc to chyba Sienkiewiczowi. Co za jakby spadek kosztu sprzętu, taki relatywny wzrost kosztów pracy za godzinę. Jednak też swoje swoje tutaj odcisnął.
Pułapki optymalizacji i koszty
Ale jest też tutaj pułapka taka jak z tymi grami w garażu było. Mieliśmy proste gry klepane w garażu przez jakiś zapaleńców i teraz mamy takiego już „Wiedźma” aka np. którego nie idzie wyklepać w garażu. No i tak samo ci goście od Javy zrobili, bo teraz to mamy tego procesora i mamy tej pamięci, a narzucają to jeszcze trochę tego, tak, tego, trochę tamtego – jakoś to będzie, a jak nie, to się powiększy stertę. W razie co wrzucimy „out of memory exception”.
No właśnie, to jest taka pokusa dla programistów i ogólnie dla twórców, że łatwo sobie teraz sprzęt i zasoby dołożyć, więc już nie musimy nic optymalizować. To też jest widoczne poniekąd w branży gier, ale w tworzeniu oprogramowania takiego zwykłego jak najbardziej, bo rzeczywiście nie da się ukryć, jeśli nie musimy się za bardzo dbać i mamy pod dostatkiem danego zasobu, tak, że też im się gra, to nie śni po nocach grożąca palcem za te przepalone niepotrzebnie tony węgla.
Bardziej. Bardziej wydaje mi się, że tutaj bardziej po nocach śni nam się menadżer, który pokazuje nam wyciągi z konta, a AWS-owego tworzy koszmary i pyta się, co to tyle kosztowało? Bo chyba tutaj jest większy taki czynnik, który, który mam, może gdzieś tam te osoby, że tak powiem, ograniczać będzie prosto. Sypało nam się na długi dach na serwisie, tośmy dali na 8 i od tamtej pory się nie sypie.
No tak, właśnie, pytanie czy lokalne jakieś proste faktory, które zwykle mamy na myśli, rzeczywiście są mierzalne w takich konkretnych liczbach, a nie gdzieś tam w cenach czy w pojedynczych dolarach dla dużej organizacji. No to może też być niewielki zysk, chociaż oczywiście im większa organizacja, ta skala jednak też robi.
No tak, ale to też się okazuje tak paradoksalnie, że im większa organizacja, tym bardziej mierzy. Chyba, bo jednak tam jeden drugiemu patrzy na ręce. No i musi być zmierzone, zapisane. Więc nie ma tak, że coś tam się przeciśnie.
Nie gorzej jest, jest tam akurat taka, że tak powiem, kultura: „Kto bogatemu zabroni?”. Jest kasiora, to ją wydajemy, mamy jakiś budżet, to to po prostu. Póki go nie przekraczamy jakoś drastycznie, a jak już się przekroczy, trzeba uzasadnić dlaczego. I dalej można. Najczęściej to jakoś tam można sobie to poustawiać. Nie gorzej jest np. chcieć teraz faktycznie wejść z liczbami, pomierzyć coś, sprawdzić i np. zechcieć ukrócić to 80%. Dajmy na to. Wtedy trzeba by się było nieźle sprężać. I tutaj już by jakaś sroga optymalizacja pewnie chciała wejść.
Tak, tak, tak, na pewno. No wiadomo, żeby optymalizować, najpierw mierzyć, żeby wiedzieć co zoptymalizować i na ile nam to się udało poprawić, jeśli w ogóle. A więc to pewnie jeszcze osobna kwestia. Jak to, jak tutaj, bo jeszcze na pewno od tego wątku wrócimy, bo to jest właśnie taki mierzenie i sprawdzanie, czy stosowanie bardziej metody naukowej. Jak tak, to to stoi mocno w kontraście do takiego zgadywania, ale na pewno tutaj poprawie jakoś to będzie. Do tego wrócimy w części już takiej bardziej…
Technicznej, technicznej, tak, tam dążącej. Więcej szczegółów tutaj. Czyli mieliśmy taką pokusę, jeszcze będąc w tych ogólnych zagadnieniach. Mieliśmy taką pokusę, że skoro było dużo zasobów, to można było je wykorzystać, więc wpisaliśmy tam ficzery i działo się to po obydwu stronach barykady. Czyli twórcy Javy robili to samo w Javie. Cały czas oczywiście tam ulepszają, wiadomo i tam poprawiają jakieś algorytmy, chociażby garbage collector związany z tym ulokowanie pamięci. Bo nie tylko czyszczenie to też ważne jest jakie struktury danych jak są używane do przydzielania tej pamięci i zarządzania nią. Później się pewnie dają lepiej czyścić nawet.
Więc my tu zakładaliśmy ficzerów od strony użytkowej, oni dokładali od strony dostawcy. I ciężko teraz porównać pewnie taką Javę 19 do Javy 1, bo praktycznie się nie da.
Można powiedzieć stał się zupełnie, zupełnie nowy. To po prostu zostało dawno i nieprawda.
Dokładnie. Dlatego teraz chcielibyśmy bardziej skupić się na tych rzeczach, które dostajemy niejako za darmo albo dostaniemy za darmo w nowszych wersjach Javy. Jeśli np. nie mamy ochoty sami sobie optymalizować, więc postaramy się przejrzeć kilka projektów, bo takich nowych nazwach, które które teraz dzieją się w community Javy i zobaczymy, co one nam są w stanie zaoferować właśnie w kontekście zwiększenia wydajności. Co możemy dostać za darmo? Jeśli tylko podbijemy support to poczekamy.
Projekt Loom
To proszę Pana, proszę. Zacznijmy może od projektu nazwanego Project Loom. Jest to chyba projekt, który w ostatnich… w ostatnim roku, w ostatnich latach zyskał najwięcej takiego rozgłosu, że tak powiem. Mimo sporego zainteresowania. Projekt Projekt Loom trwa już mniej więcej 6 lat, bo zaczął się przed 17. I to trzeba sobie jasno powiedzieć, że to jest długość trwania takich projektów grubszych w Javie. To jest współczynnik, że jednak te zmiany, które są wprowadzane, to w dużej mierze jednak dotykają dość fundamentalnych kwestii języka, składni, w ogóle działania pod maską.
Ale idzie nam się śpieszy, widzę, mam, przyspieszam.
Oczywiście jeśli dostaniemy to kiedykolwiek, tak naprawdę będą tam te obiecane ficzery, no to i tak będzie dobrze. Natomiast wracając jeszcze do tego projekt projektu Loom, co on właściwie nam daje jako główną? Jego główną wartością ma być wprowadzenie nowego modelu obsługi wątków. Coś, co będzie się nazywało Virtual Threads, czyli wirtualne wątki. Ten ficzer jest już dostępny w Javie 19, więc możemy go sobie użyć. Czasami po prostu trzeba odpalić program z odpowiednią flagą. No i na czym to wirtualne wątki polegają i co to właściwie nam daje? Tutaj sobie można na początek odświeżyć. W ogóle jak? Jak wygląda obsługa wątków w Javie i dlaczego? Może też tak rzadko z tego korzystamy?
Wątki w Javie
Kurde, nie wiem, czy nie trzeba by najpierw odświeżyć w ogóle o co chodzi z tym procesorem?
No to powiem w ogóle o co chodzi z tą Javą, bo w części pewnie technicznej.
No może do tego trochę zbyt wczesna, dość szczegółowa, ale tak pokrótce o to też zahaczymy tutaj.
No dobra, to co? Proszę o tych wątkach. Zaczyna się robić ciekawie. Generalnie wątki w Javie są. Obsługiwane są tak naprawdę ma po same praktycznie jeden do jednego do wątków systemowych. Jest to nazwane Platform Threads i to generalnie sprowadza się do tego, że dla każdego wątku czasowego mamy właściwie jeden wątek systemowy. I problematyczne w tym podejściu jest to, że obsługa takiego wątku. Właściwie stworzenie takiego wątku platformowego jest dość złożone obliczeniowo, a jednocześnie też pamięciowe, pamięciowe już ze względu na specyfikę Javy, która dla każdego wątku rezerwuje sobie kawałek pamięci na stacku właśnie i każdy wątek ma tam swój kawałek, swój kawałek stosu, tam trzyma swoje lokalne zmiennej, jakieś tam referencje do zmiennych _heap_a, ale generalnie jest to nasz ten kawałek kawałek przestrzeni, gdzie możemy trzymać dane. Jest to przestrzeń, która nie podlega. Zmianie pod kątem rozmiaru, więc wiadomo, że musimy tą przestrzeń, tą tą kawałek pamięci na stosie zarezerwować z odpowiednią w odpowiednim rozmiarze, żeby jednak tamtej pamięci starczyło. A dla poszczególnego wątku jeśli pamięć nam zabraknie, no to leci nam Stack Overflow Exception, czyli znany tutaj wyjątek, który często na to stać, nawet jeśli mamy załączoną rekurencja. No bo też na tą pamięć odkładane są ramki wywołania poszczególnych funkcji, więc tutaj pętelka. Ładnie ładnie to co to to cały czas wypełnia. I teraz tworzymy sobie taki wątek. Obecnie w Javie to. No to zawijamy sobie kawałek pamięci i tu mówimy o 8 MB pamięci, więc to troszkę jednak jest plus. To troszkę kosztuje obliczeniowo. Siłą rzeczy nie da się tego robić bardzo często. Do tego wątki łączymy wątków, dlatego musimy tutaj używać pewnych optymalizacji, żeby tych wątków jednak nie tworzyć na potęgę.
To, co wprowadza projekt z projektem, to są wirtualne wątki, które będą odseparowane od wątków platformowych, od wątków systemowych. I dzięki temu będziemy mogli tworzyć właściwie w locie. Tak jak? Tak jak normalne obiekty, bez żadnego opluwania, bez żadnego można powiedzieć dbania o to, żeby, żeby gdzieś tam tworzyć wydajnie, bo one mają być lekkie. One gdzieś tam wewnętrznie będą podczas pana Podwiązki systemowo, a to już nas nie interesuje, nie musimy się tym przejmować. Generalnie to będą, jeśli chodzi o z punktu widzenia API, czy z punktu widzenia wykorzystania przez programistę. Można powiedzieć, że to będzie normalny wątek, taki jak używamy obecnie z.
Od razu widać pewną zaletę. Nie będziemy musieli marnować pamięci na aż tak dużo, przynajmniej na stworzenie tego wątku. Będą one znacznie, znacznie lżejsze w samym stworzeniu, jeśli chodzi o proces obliczeniowy.
I to diabłem będzie dbał o to, żeby tam jakoś wykonywać tak, tak, powiedzmy pseudo współbieżne.
Tak, tak, tutaj jakby nie musimy się absolutnie przejmować jakimiś tam szczegółami implementacji innymi. On oczywiście potraktowany jak normalne wątki API bardzo niewiele się zmienia, więc tutaj nie musimy się jakoś specjalnie tym przejmować. No i dzięki temu możemy sobie te wątki właściwe wykorzystywać w sytuacjach. W których do tej pory może tak niekoniecznie byśmy w wątki poszli, czy nawet do każdej operacji, którą możemy równolegle wykonać kilka rzeczy na raz. Tu teraz stworzyłem takiego wątku, bo to będzie znacznie prostsze. Nie musimy się przejmować, że jest to ciężkie, niewygodne czy czy w jakikolwiek sposób nadwyręża naszą, naszą maszynerię. Tu na pewno największy potencjał jest w serwerach aplikacyjnych, czyli znany model Frag Quest, czyli dla każdego przychodzącego użytkownika. No zwykle każdy request ładowany w osobnym wątku. I tutaj są znane te ograniczenia w ilości serwerów czasowych i ilości użytkowników, których możemy obsłużyć jednocześnie właśnie ze względu na tą niewielką.
Niewielką oczywiście. Jednocześnie wykonywanych wątków mamy tyle, ile mamy wątków w danym procesorze, ale samych wątków możemy stworzyć znacznie więcej. To już jest kwestia ile jednocześnie będzie odpalonych. Generalnie tak przykładowo, żeby tutaj zarzucić troszkę liczbami, to rzucę tylko przykład dotacje zaczerpnięte, chociaż liczby oczywiście będą się różnić od poszczególnego sprzętu. Wiadomo, to są zasoby, ale takie testy na stworzenie jakiejś tam nieograniczonej ilości tych starych zwykłych wątków no to zamknęło się w około 32 tysiącach wątków i po tej liczbie mniej więcej już nastąpił. Autor no, może jak Generalnie już więcej się nie da, bo już wyczerpaliśmy całą pamięć. I na tej samej maszynie. Autor wtedy tworzył wątki lżejsze, ze spektrum mocy, spokojnie doszedł do liczby 1 miliona.
Na stówę lody Jacka. To one działały tam cały czas.
Tak sobie chodziły pod spodem i oczywiście scheduler musiał tam odpowiednio nimi zarządzać, żeby. Oczywiście jednocześnie wciąż wykonuje się tylko tyle, ile mamy wątków na procesorze, czyli nawet w najlepszych procesorach. To 30 parę powiedzmy, ale możemy ich stworzyć tyle I dzięki temu jednak tych użytkowników gdzieś tam teoretycznie możemy na tych użytkowników. Handlować, więc. Jednocześnie jest to o rząd wielkości większa większa liczba. No i to też jakieś tam daje lepsze, lepsze możliwości. Oczywiście stworzenie tych wątków nie spowodowało wyrzucenia błędu o braku pamięci. To oczywiście zaczęło strasznie zwalniać te aplikacje, no bo wiadomo jak stworzymy się częściej włączało niż coś wykonywało.
Tak, tak. No właśnie, to też przyłącza kontekstu do tych wątków. No nie da się stworzyć miliardów, no bo procesor musi jednak kawałek czasu dać każdemu wątkowi. Jak będzie ich za dużo, to wiadomo, że więcej czasu stracimy na przełączanie się pomiędzy nimi. Ale sama jak tutaj skala właśnie pomiędzy starym a nowym rozwiązaniem jest jest dość znacząca.
Netty i reaktywne podejście
A to zalatuje jakby taką inspiracją, takim wynalazkiem jak Netty np. gdzie tam się operowało na bankach. Tak to było nazwane zdaje się Papi. Tego sreberka używam, bo to jest. Nie wiem jak to się teraz rozwinęło, bo już dawno tam zaglądałem w ogóle, ale wiem, że Netty leży u podstaw sprytniejszy. Serwera kontenera właściwie takiego reaktywnego, chociażby wykorzystywanego w Springu. Gdzieś tam była możliwość włączenia sobie takiego wynalazku i tam pod spodem wtedy było odpalone zamiast Atom Gate. A Netty ma tą fajną właściwość, że właśnie nie obsługuje _request_ów wątkach tylko w takich w czymś co twórcy nazwali czcionkami, czyli takimi cząstkami kodu, które po prostu były traktowane jako takie. Malutkie wykonywa brane na chwilę, wykonywane i odkładane. Podobnie zarządzane jak wątki, tylko bez całego tego kosztownego przełączania kontekstu, z mniejszym przełączaniem kontekstu wewnątrz niej. Wtedy być może kilka wątków takiego serwera było w stanie te swoje mikro wątki, bo to jest już takie pojęcie, które gdzieś tam się w literaturze też pojawiało i niekoniecznie w Javie i zawsze właśnie w takich zarządzanych osobno wynalazkach.
No tutaj chyba to jest bardziej takie to, o czym mówisz, to takie bardziej podejście reaktywne i to. To jest chyba też coś, co cały taki stack reaktywny troszkę wyszedł właśnie. Dzięki temu, przez to, że ta wielowątkowość w Javie jednak była w pewien sposób ograniczona, żeby zwiększyć te przepustowości, czy to liczbę wykonywanych operacji, czy obsługiwanych użytkowników, to właśnie stack reaktywny pozwalał na takie zwiększenie. No bo jednak nie. Nie czekaliśmy na odpowiedź tego czy jednego, tylko testowaliśmy kodeka i ten kodek dopiero był wykonywany w momencie, kiedy wynik był gotowy do odtworzenia. I tutaj wirtualne wątki są troszkę równoległe, jakby rozwiązaniem. Teoretycznie mogły być trochę prostszym, no bo jednak reaktywny stack. To wymaga też interaktywności, można powiedzieć od początku do końca. Tak czy tak jak mamy Spring np. reaktywne MVC. Do tego musi być też aktywny serwer i pewnie jakaś też reaktywna, reaktywna połączenia do jakiejś warstwy prezentacji, jeśli mamy. Paradygmat reaktywny wymaga troszkę więcej przygotowania, żeby zapewnić to podejście na całym obszarze naszego rozwiązania. Natomiast wątki możemy przy tym kawałku kodu, który mamy stworzyć ten wątek, oddelegować do niego jakieś wykonanie zadania i pozbierać wyniki poszczególnych zadań. Nie jest to aż tak narzucające jakieś.
Narzucam jakoś specjalnie specyficzną konwencję. Mamy tu trochę tak długo, jak pozostajemy w konwencji tego właśnie zarządzania wątkiem, czyli tworzenia jakiegoś zadania w jakiejś formie i przekazania go do wykonania. Później co najwyżej ubicia go, jak już nam jest niepotrzebny zwrot do puli czy coś.
No to co? Pewnie to przypomina ten model klasycznej takiej piątkowa kości.
No to się zwykle porównuje, bo do do computing, czyli do tych rutyn z języka Go. Skoro tym z Kotlina trzeba sobie jasno powiedzieć, że wątki nie są odpowiedzią i rozwiązaniem na wszystkie problemy świata, albo chociażby programowania samego w sobie, bo jednak nie wszystkie rzeczy da się równolegle. Tutaj musimy, musimy tak mieści już to jest, które pozwala nam na zrobienie tych kilku rzeczy jednocześnie.
No właśnie, bo bo wspomniałeś, że i tak się wykona tylko tyle wątków równolegle, ile mamy wątków sprzętowych.
Tak, tak. To o co chodzi z tymi wątkami sprzętowymi? Generalnie wątki sprzętowe zależą oczywiście od ilości wątków dostępnych na naszym procesorze i tylko tyle możemy ich jednocześnie wykonywać ile obsługuje nasz procesor. Minus oczywiście jakieś tam wątki, które są już gdzieś tam przez system zajęte, więc nigdy nie będziemy maksymalna ilość. Natomiast pozostałe wątki graczy czekają na swój a swój kawałek czasu procesora, bo i scheduler odpowiednio tym czasem zarządzając. Daje nam to złudzenie takiej sekwencji ności wykonania procesu w danym wątku, a tak naprawdę jest to bardziej podzielenie na kawałki tego czasu procesora w ramach tego konkretnego wątku na danym procesorze. Tutaj mamy to wzbudzania wykonania czy. Wykonywania wielu operacji na raz. Natomiast wszystko to się dzieje z jakimś tam podziałem czasu i z odpowiednim zagospodarowaniem tego czasu i dostępnych wątków i dostępnych zasobów. Zaczyna się od danego właśnie zużycia, obciążenia i wielu innych rzeczy. To jest kwintesencja.
Czyli ten zarządca wątków. I idąc dalej zarządca procesów musi być tak sprytnie napisany, żeby jednak nam to złudzenie zapewnić.
Nie ma go tak pod spodem, a jakąś tam pulę w sprzęcie rdzeni tak naprawdę w procesorze? Powiedzmy, że na takim typowym laptopie, na którym się już w miarę laptopie trochę tutaj, że tak powiem, zdradziłem na czym to się teraz pracuje, ale można sobie w dowolny komputer wyobrazić, który ma powiedzmy 4 rdzenie. Z takich niespecjalnie. O niebotycznych cenach to to takie 4 rdzenie fizyczne, czasem 8, podzielone na każdy, na 2 wątki sprzętowe. To daje 16 wirtualnych rdzeni np. przy takim 8 rdzeniowym procesorze, a przy 4 rdzeniowym daje nam 8. Czyli tak między 8 a 16 wątków mamy do dyspozycji do odpalenia równolegle.
Czyli powiedzmy może być. To oczywiście mogą być różne wątki z różnych procesów, ale one dostają fizycznie te rdzenie procesora, które są aktualnie dostępne i na nich się wykonują już naprawdę. Równolegle w tej naszej rzeczywistości niestandardowej już mamy tę równoległość i ich koledzy czekają w kolejce. I kiedy nadchodzi moment przełączenia kontekstu, są po prostu te stare, wykonane już kawałki wywalczone i w ich miejsce są ładowane kolejne z tej kolejki, a pamięć z każdego spotkania jest zmieniana.
No i tak prosto Prezes. Stos to jest genialny wynalazek, tak szczerze powiedziawszy.
Przyszłość wątków w Javie
No właśnie i tutaj ten projekt jest chyba z tych, o których będziemy dzisiaj mówić, chyba w najlepszej tutaj takiej największej zaawansowanej fazie. Wątki wirtualne możemy sobie sprawdzić w preview, do tego jeszcze będzie dodanych kilka usprawnień. Ogólnie w takiej wielowątkowości coś co się nazywa strach wśród konkurencji. To między innymi ma naprawiać kilka problemów, które wynikają. To specyficzne sytuacji, które które mamy. Jeśli chodzi o podzielenie wątku wątku na jakieś taski, na jakieś przecieki, straty lighting tzw. generalny troszkę usprawni nam, że tak powiem, organizacja tego naszego kodu jeśli chodzi o wielowątkowe struktury. No bo jeśli teraz rzeczywiście możemy sobie te wątki tworzyć na potęgę, to jednak kod do obsługi wątków i obsługi błędów też musi być w miarę niezawodny, żeby żebyśmy gdzieś tam nie stracili tych naszych zasobów czy danych. Niemniej jednak trzeba, jak to w dużej ilości artykułów się podkreśla. Trzeba by z kilku rzeczy się oduczyć, czyli chociażby tego pulsowania wątków, albo nie bania się tworzenia wątków w locie. No bo teraz wirtualne wątki po prostu tworzymy jak leci i reagujemy do nich nasze poszczególne poszczególne taski czy inne rzeczy, które chcemy. Wykonać. Także zapowiada się ciekawie. I może rzeczywiście.
Zarządzanie pamięcią i Project Valhalla
A jak to jest z pamięcią w tych wirtualnych z pamięcią? Co masz na myśli dokładnie np. wątek. Wątki normalne współdzielą pamięć tego samego procesu. W sensie na starcie. Następną to te tutaj. One mają jakiś inny model zarządzania swoją pamięcią, czy po prostu też nie ma tu doświadczeń, co zmieniają się w to, co, co maszyna daje?
Tak, tak, tak, tak, tu będzie tak samo. Dalej pamięć na stercie jest współdzielona, więc jakby wszystkie problemy, które mamy z synchronizacją czy z wielo dostępem, czy z jakimś fast conditions to dalej będzie. Tutaj Project Loom nie ma zamiaru. Nie, jego zadaniem jest, żeby tutaj naprawiać jakieś problemy współczesności. Tutaj wciąż będziemy musieli sekcjami synchro na S3, jakimiś volatile. Wciąż będziemy musieli dbać o to, żeby ten kod był bezpieczny wątkowi. I tutaj też nic się nie zmieni. One nie będą to lżejsze wątki, one nie będą, że tak powiem, bezpieczniejsze. Jeśli o tym mówimy, to wszystko jest tak samo, jeśli chodzi o model pamięci. Też niewiele.
Niewiele się nauczyli, ale ta ich lekkość, to wynika z tego, że po prostu przechodzą pod skrzydła jej FEMA. Czyli unikamy tego rozbudowanego mechanizmu zarządzania przez system.
Unikam tego systemowo opartego, tego złączenia bezpośredniego z wątkiem z wątkiem systemowym. Więc tutaj tutaj jestem największa, największa zaleta, no i w miarę w miarę w miarę niewielkie zmiany w API, więc to będzie na pewno jakiś tam plus. To wiadomo też trochę. Twórcy bibliotek będą musieli się też trochę do tego przygotować. Gdzieś tam już też trwają, trwają prace, żeby, żeby, żeby się do tego przygotować. Więc to jest. To jest dość szeroka inicjatywa, dlatego pewnie potrwa już dobrych 6 lat. Ale sam fakt, że jest, to już jest na to jakaś szansa, żeby w ciągu niektórzy nawet następnych sześciu następnego roku to prawie to. Nawet w ciągu następnego roku wirtualne wątki mogły już wejść do normalnej wersji z nową wersją okładkę.
Dobra. Następną rzeczą i to projekt, który trwa jeszcze dłużej i też na razie ma problemy, żeby żeby jakoś sensownie dojść do celu. Jest projekt o nazwie Valhalla. I nie mamy tu na myśli nowego Assassin’s Creeda, a projekt, który zaczął się już. Koło roku 2014. Jest tam podobno pierwsze. Były pierwsze przymiarki do tego projektu. Projekt Jego założenia polegają na pewnej unifikacji modelu danych, jeśli chodzi o obiekty. Jeśli chodzi o typy prymitywne, pewne pewne zasypanie takiej przepaści można powiedzieć, na czym to polega. To jest takie ogólne stwierdzenie, że mamy unifikację naszego modelu danych. Otóż może też chwila przypomnienia, o co właściwie chodzi, jeśli chodzi o taki model danych. Jak wszyscy wiemy, w Javie mamy typy prymitywne, czyli te wszystkie maszyny int, boolean, double itd. Mamy do tego klasę i tablice. To są tak naprawdę podstawowe building bloki, podstawowy building bloki, które za pomocą których tworzymy nasze systemy, za pomocą których modelujemy nasze obiekty, nasze klasy. No i problemem tak naprawdę z obiektami jest to, że czasami to, co modelujemy niekoniecznie musi posiadać tożsamość. Czasami byśmy chcieli, żeby to było totalnie inni osobą, bo to nie ma żadnej tożsamości. Nie potrzebujemy, żeby to występowało w kilku instancjach, bo wiemy, że tak naprawdę ten obiekt konkretny jest jedynym naszym obiektem i on nie musi być w różnych instancjach, w różnych instancjach, które zajmują oczywiście swoją pamięć, zajmują oczywiście przestrzeń na naszej stercie. Więc celem tego projektu jest wprowadzenie czegoś, co się nazywa Value Classes. Czy to są. Klasy, których obiekty nie będą owalne. I tak naprawdę Java powinna nam wtedy zagwarantować, że to będą po prostu pojedyncze instancje nie mające żadnej tożsamości. Coś można powiedzieć jak takie w stylu snobów rozszerzonych no błędu. My też mamy tutaj gwarancję.
Obraz użyj wszędzie.
Tak, tak, tak, tak, Tutaj mamy też maszyny. W przypadku _end_ów gwarancję, że mamy tylko jedną instancję danego wnuka. Dlatego np. robimy porównanie podwójnym równa się bowiem tak naprawdę zawsze pojedynczo nie porównujemy, zawsze referencja w pamięci będzie taka sama. Taki obiekt również będzie gwarancją, że będzie występował tylko w jednej instancji. Do czego to może być przydatne, pomijając rozszerzenia?
Tak naprawdę, jak modelujemy jakieś klasy, na przykład często podawany przykład układu współrzędnych i jakiejś tam wartości punktu, czyli Point, który ma x i y, to czy jest sens, żeby w naszym systemie on był w kilku instancjach? Czym się różni taki Point (10, 10) od innej instancji Point (10, 10)? Niczym się nie różni. To dokładnie ten sam obiekt. Natomiast jeśli robimy sobie aplikację, wczytujemy sobie te współrzędne, tutaj tworzymy coś tam, tam przychodzą nam z interfejsu. Wszędzie tworzą nam się nowe instancje tych Pointów (10, 10). Po systemie śmiga tysiące, czasami już dym ze sterty leci. Wszystkie te pointy są innymi instancjami. My tam piszemy equals
. W equalsach
piszemy, że jeśli X równa się X i jeśli Y to Y, to jest ten sam Point. To wtedy to oczywiście jest ten sam, ale to wciąż jest tak naprawdę bezsensowna robota, bo my wiemy, że ten Point powinien być po pierwsze niezmienialny, a po drugie powinna być tylko jedna instancja tego Pointa, bo to nie ma sensu, żeby były dwie. Nie ma po prostu żadnego przełożenia na ten model, który reprezentuje obiekt Point. Podobnie to też nie powinno być w sumie budowane, bo z tym Pointem raczej stworzymy sobie nowy, jeśli chcemy coś tam przeliczać. A ten konkretny Point raczej nie będziemy modyfikować. Nie ma jakiegoś stanu, sam jest stanem, dokładnie, bez żadnej tożsamości. Tylko że w obecnej składni Javy nie możemy sobie w żaden sposób tego zamodelować.
Oczywiście możemy zrobić pola finalne, czyli nie będziemy tych pól móc modyfikować. Możemy zrobić klasę final, wtedy tanio dochodzimy do Pointa, co nie będzie miało w pierwszej połówce X, a w drugiej Y. Tak, możemy się oczywiście bawić w różne inne.
Mamy tu po prostu silnik szachów, piszemy na przykład.
Tak, możemy pokusić się o odpowiednie optymalizacje, wykorzystując właśnie te typy prymitywne, ale jak fajnie by było mieć klasę, która mogłaby być właśnie takim pseudo typem prymitywnym. Właśnie te Value Classes i tworzone z nich Value Objects byłyby właśnie takimi klasami, które reprezentowałyby obiekty bez tożsamości. Te klasy miałyby standardowe, można powiedzieć dowolne metody, które sobie do nich dołożymy. Zachowywałyby się generalnie tak samo jak normalne klasy, z tym że nie ma wtedy obsługi polimorfizmu, bo tutaj te klasy nie mają tożsamości aż za bardzo. Tutaj struktura dziedziczenia też nie do końca do tego pasuje.
Co nam w ogóle to daje, że te klasy są trywialne? Po pierwsze daje nam to bardzo duże możliwości dla Javy pod kątem optymalizacji rozłożenia takich obiektów w pamięci, bo wtedy nawet te wielkie pule… Popatrzmy na stringa. Przecież string w Javie również jest niemodyfikowalny i właśnie z takiego samego powodu to jest podobne rozwiązanie, też pod kątem optymalizacji po to, żebyśmy na stercie nie mieli tam latających stringów, takich samych de facto łańcuchów znakowych, ale różnych obiektów stworzonych z różnych części aplikacji. To ma być, tu ma być naprawione od podstaw, że tak powiem. Wtedy tego typu obiekty, które z zasady nie mają tej tożsamości, mogą być spokojnie odwzorowywane przez klasę, która to wyraża. Dzięki temu JVM będzie mógł sobie to elegancko w pamięci upakować, zapewnić, że będzie to pojedynczy obiekt, przeprowadzić kilka różnych optymalizacji, które możemy na takich obiektach przeprowadzić. Generalnie to są.
Unikamy wtedy po prostu wskaźników na te obiekty. To są nasze konkretne obiekty, to są nasze konkretne wartości. Nie potrzebujemy robić do nich referencji, bo one są generalnie niezmienione, więc daje nam to bardzo, bardzo duże oszczędności, że tak powiem, na ich tworzeniu. Do tego ma być jeszcze coś, co się nazywa Primitive Classes w tym projekcie również, chociaż tutaj zdaje się jeszcze trwają dyskusje na czym to ma polegać. Generalnie Primitive Classes to miał być jeszcze poziom niżej, można powiedzieć, pod Value Classes, czyli to już takie naprawdę bardzo proste wrappery na prymitywne obiekty, z również ze wszystkimi ograniczeniami, które prymitywy mają. Ale tutaj jeszcze może być troszkę dyskusji na ten temat.
Jak się okazało pod koniec zeszłego roku i tak jak powiedzieliśmy tutaj, największy zysk to właśnie unifikacja tego podejścia i rozwiązanie tych problemów. Obiekty prymitywne kontra typy prymitywne. I to dzięki temu będzie można troszkę lepiej zaadresować generyki czy też znany problem generyków, gdzie typy generyczne nie mogą być typami prymitywnymi, więc musimy tam robić jakieś intuicje czy inne duże obiekty i wchodzi tam auto boxing, a co za tym idzie, pewne również zwiększania zapotrzebowania na pamięć i wszystko co się z tym wiąże. Jest tutaj kilka takich rzeczy, które można zunifikować i uprościć i dzięki temu ten model taki właśnie obiektowo-prymitywny, czyli tych typów prymitywnych jakoś to bardziej połączyć. De facto wtedy już właściwie tych typów prymitywnych prawdopodobnie by nie było. Mielibyśmy te dwa obiekty, a te typy prymitywne stawały się tymi czasami prymitywnymi. Więc tutaj jest spore pole do manewru.
Ten projekt, Project Valhalla, jest chyba jednym z takich bardziej mocno idących, jeśli chodzi tak naprawdę o głębokość zmian, bo to jednak dotknie bardzo podstawowe części Javy. Jaka jest w ogóle definicja struktur podstawowych bez tych bloków, których mamy w języku? Więc też nie ma co się dziwić, że ten projekt trwa już dobrych 9 lat i jeszcze nie widać tak naprawdę za bardzo…
Projekt Leyden
Ja też się nie dziwię, bo ja kiedyś sobie wziąłem źródełka dwunastki, wrzuciłem Liona, żeby zobaczyć, jak to jest właściwie z tą pamięcią przy tym obiekcie i obiektu nie mogłem znaleźć. Czyli po prostu widać, że to, co widzimy, to… Zaraz. Dlatego tym się zajmę. Kolejne prowadzenie ma… Aha, myślałem, że po prostu jest tam jakaś inna klasa, obiekt, która leży u podstaw całej Javy i ja ją tutaj zaraz zacznę rozkminiać, coś tam w niej uproszczone skompiluję i będzie. No może nie do końca, ale jest jedną z rzeczy.
Więc jak taki mają kodzik, to może zejść te 6 lat spokojnie.
No tak, tak. Trzeba pamiętać, że robiąc tego typu zmiany, to jednak dotykamy milionów linii kodu, które będą później tych zmian używać. Jeśli kiedyś mieliśmy stracha, żeby zmienić jakiegoś Dawka w naszym projekcie, a do Arki użyć wód Szymon, Alicja czy gdzieś tam i to nas przerażało, to teraz pomyślmy jakiego stracha muszą mieć autorzy, którzy chcą zmienić coś w Javie i później wszyscy muszą tego użyć.
Na pewno ciekawa rzecz. Także jest to dość ciekawa zmiana i to trzeba na pewno obserwować. Zobaczymy. Jeśli tego typu zmiany rzeczywiście ujrzą światło dzienne, to będą znaczyć sporą rewolucję, jeśli chodzi o podejście ogólne do modelowania wielu rzeczy w Javie i też dadzą na pewno wymierny efekt, jeśli chodzi o wydajność.
Kolejny projekt, który też jest gdzieś tam w rozważaniach, już właściwie w zaawansowanej fazie, to projekt o kodowej nazwie Leyden. Projekt ten głównie polega na czymś, co w ostatnich latach trochę w ekosystemie Javy stało się dość popularne, a mianowicie na opóźnieniu i wyleczeniu w czasie pewnych operacji, które wykonujemy na starcie w jakimś tam trap’ie przy uruchomieniu aplikacji. Celem tego programu jest właśnie w pewien sposób skonfigurowanie możliwości właśnie wyłączenia pewnych ficzerów Javy, czy to jakiś tam refleksji, i położenie nacisku na lezing jest więcej i bardziej takie AOT (Ahead-of-Time) kompilacji. Autorzy tego projektu chcą to osiągnąć za pomocą takich klas, które oni sobie nazywają “users”. W sumie nie wiem, jak to polskie tłumaczenie na to znaleźć. Zagęszcza czy zagęszcza cebulki? Może to coś, to coś może takiego? I to mają być takie generalnie transformaty, konfigurowalne transformaty, które mają nam te ficzery włączać, wyłączać i w ten sposób nam to uruchomienie optymalizować.
Tutaj nie ma chyba jeszcze za bardzo takich konkretniejszych przykładów, więc tutaj autorzy obiecują oczywiście po raz kolejny zmniejszą zużycie pamięci. Jak te wszystkie projekty wejdą w końcu na produkcję, to w ogóle nam… W ogóle nie będzie używać. W ogóle nie będziemy używać. Pojęcie “siła” będzie dawać tej pamięci, bo okazuje się, że każdy projekt tutaj nam oszczędza.
Redukcja nagłówka obiektu
To chyba też dowodzi tak naprawdę właśnie temu podstawowemu problemowi Javy, czyli właśnie tej zajętości pamięci. Rzeczywiście, chyba to i dlatego pewnie też te paręnaście lat temu to był taki problem, kiedy tej pamięci może aż tak dużo nie było. Java dużo potrzebowała. Więc teraz te projekty idą bardziej w tę stronę.
Tak, to są takie główne i najciekawsze, można powiedzieć, projekty, które się teraz toczą w ramach właśnie inicjatyw jałowych. Natomiast mamy jeszcze kilka takich rzeczy, które również potrafią nam przyspieszyć wykonywanie. Tutaj na pierwszym miejscu chyba się w sumie wysuwa GraalVM i jego Native Image.
Brzmi groźnie, brzmi groźnie.
To jest też troszkę taki powrót, może nie do korzeni, ale rzeczywiście po raz kolejny stwierdzenie, że w sumie jeśli Emka jest na co, to komu, na co to komu? Więc może troszkę się jej pozbądźmy.
I to trochę na tym, na tym polega, bo to by dopiero dało tą pamięć tamtego.
No bo Native Image polega na zbudowaniu naszej aplikacji w postaci wykonywalnego artefaktu, specyficznego dla danej platformy. Czyli nie mamy już jakichś JAR’ów, mamy po prostu…
Czy tu dopiero możemy sobie zbudować obraz Dockerowy, czy po prostu platformowe table? No i możemy to uruchomić już w ogóle bez kodeka.
Ten artefakt, który powstanie w tym natywnym image’u, będzie zawierał w sobie wszystko, co prawdziwie w trakcie budowania oddaje, czyli wszystkie klasy zależne, wszystkie niezbędne elementy, które są potrzebne do wykonania, jakieś pojedynki, cokolwiek, co po prostu będzie niezbędne, żeby ten nasz projekt wykonać. I to zostanie zbanowane, zbudowane i gotowe. Tak naprawdę mamy aplikację webową, która już nie jest aplikacją webową, bo nie chodzi już na jej więcej. To nam oczywiście da zmniejszone, czyli zmniejszone zużycie pamięci po raz kolejny, no bo to już nie jest natywne.
Dlatego tutaj chyba promocje nie sumują się.
Tak mi się zdaje, bo to już będzie całkowicie inny model. To… Nie wiem. Nie wiem, jakby miały zadziałać te, na przykład, zmniejszone Headers, skoro tutaj pewnie i tak jest…
To dość oczywiste.
Tak, wtedy rzeczywiście zadziałają, no bo już generalnie już nie mamy nawet kodu.
No właśnie, to wszystko, co się tyczy specyficznej Javy, już, już nie ma. Nie ma refleksji, nie ma bytecode’u. Nie, tak to ma być.
No tak, to już jest Java bez Javy de facto, więc tutaj są pewne ograniczenia. To trzeba sobie jasno powiedzieć, że chłopaki z C++ ucieszą się.
Tak, ale trzeba sobie jasno powiedzieć, że są pewne ograniczenia. Samo budowanie trwa dość długo, więc to też nie jest coś, co możemy sobie tak, deweloperzy, wykonywać.
Kompilować. Kiedyś Gentoo, to, to dopiero, ale znam kogoś, kto kompilował. Ja to znam. Także także to na filmie może to być fajne rozwiązanie, jeśli mówimy o jakichś lambdach, które potrzebujemy, żeby szybko odpalić. No i nie mamy wtedy runtime’u, czyli po prostu pożarnych…
Tak, aplikacjach.
Znaczy runtime jest, przepraszam najmocniej, bo zawsze jest, tylko nie jest.
Java. Frontend. Bibliotek jest platformą.
Platformą? Tak? Trzeba sobie jasno powiedzieć, że to tak jak wspominałem, nie ma bytecode’u, więc też nie jest to “pakujemy sobie”. Integrują takiej aplikacji tak drzewo, bo zawsze dostaniemy jakiegoś tego umpa gołego i możemy go wsadzić w Visual A. Tutaj mamy tylko na jakieś tam THU do dyspozycji. Również są pewne ograniczenia, jeśli chodzi o zewnętrzne biblioteki. No bo tutaj następuje taki troszkę tree shaking, czyli usuwanie kodu, do którego z punktu widzenia istoty analizy nie możemy się dostać i kompilacja tego kodu do natywnego, który mamy w projekcie. Nie wszystkie biblioteki mogą być od razu out of the box.
GraalVM ma takie repozytorium, GraalVM Substrate VM Native Image Build Configuration Repository, czyli jakby listę z dość nowymi konfiguracjami per biblioteka, które właśnie definiują, które klasy powinny być brane pod uwagę w przypadku builda. Tak, żeby rzeczywiście nie było żadnego problemu z dostępnością tej czy innej klasy czy obiektu natywnego. Wręcz, wręcz. Jest to troszkę taki proces rozbudowany, specyficzny, dość już nisko grzebiąc w naszych czym, może nie tyle grzebiąc, de facto dostajemy troszkę inny artefakt niż JAR, niż inne aplikacje. Więc warto o tym pamiętać, że to już nie będzie wtedy Java.
Frameworki dla szybkiego startu
No tak, ale tak długo, jak będziemy to traktować jako taki właśnie niezależny artefakt i być może do takich osób, które właśnie akurat takiego czegoś wymagają, wtedy spokojnie, bo nie trzeba się będzie martwić, że tam w locie musi nam się coś doładować, bo to chyba czasy doładowywania w locie tych klas przesyłanych po sieci, to już chyba odeszły do lamusa.
Zasłużonego.
Zasłużonego?
No właśnie, a gdybyśmy nie chcieli iść tak daleko jak Native Image, a jednocześnie móc, na przykład, tą przysłowiową lambdę odpalić troszkę szybciej niż zwykle, niż tamten Spring startuje? Co by tu zrobić? No bo jednak jakby nie patrzeć, szybkość aplikacji webowych to jedno, ale jeśli mówimy o chmurze, to tutaj potrzebujemy czegoś szybszego, żeby nas te serwery z lasem… są serwery, ale chcielibyśmy, żeby to szybko startowało, no bo to jednak to w C++ będziemy pisać, ale gdybyśmy uznali, że jednak C++ to nie jest dla nas, bo znamy Javę i chcemy robić w Javie i chcemy mieć jednak tą naszą lambdę w Javie owcach i żeby też co nieco w Javie i też nie w Pythonie i nie w Node.js.
Pythonem to sam bym się bał.
No właśnie, więc tutaj na pomoc przychodzą nam specjalistyczne, można powiedzieć, frameworki, które właśnie chcą zaadresować kilka problemów, które Java, głównie Spring, ze względu na swoją już dość dużą masę krytyczną, że tak powiem, bo nie da się ukryć, że Spring, jego start jest dość powolny i przez to jest taki powolny. Spring bardzo dużo rzeczy robi w runtimie. Tak, skanowanie naszego, skanowanie naszych adnotacji, robienie jakiś dynamicznych proxy. Wszystko to powoduje, że wszystkie klasy trzeba załadować do pamięci. Refleksja działa tak, że nawet jeśli dotkniemy pojedynczego malutkiego pola, żeby coś sprawdzić, to całą klasę oczywiście musimy załadować. Więc to też raz, że trochę to trwa, a dwa, że zajmuje nam trochę pamięci. Wszystko to robimy w runtimie. Więc na dzień dobry, na starcie musimy to przeskanować. Spring musi przeskanować swoje rzeczy. Hibernat musi przeskanować swoje rzeczy. Jakieś biblioteki docelowe oczywiście skanują to tam swoje rzeczy. No i jeszcze my dołożymy tych adnotacji. Oczywiście mamy nasze własne adnotacje, więc jak wszyscy zaczną to wszystko skanować…
I jedynie sprytny Lombok gdzieś tam na Compiler porobił te nasze wszystkie konstruktory i value classes, więc on chociaż uniknął tego syndromu.
No ale tutaj tutaj ta magia frameworka trochę daje się we znaki. Dlatego ten cold start, ten cold start, czyli ta metryka, która jednak w serverlessie jest dość ważna, no nie jest najlepsza. I tutaj z pomocą przychodzą nam frameworki takie jak Micronaut i Quarkus. Micronaut jest troszkę starszy, Quarkus ciut nowszy. Oba już mają kilka ładnych lat i generalnie ich celem właśnie było przyspieszenie Javy właśnie w takich użyciach aplikacyjnych, w serverlessach. Ich specyfiką jest to, że starają się jak najwięcej rzeczy robić w compile time.
Historia i alternatywy dla Springa
Kiedyś taki już chyba się nazywał. On też chyba taką dajmy sobie robił tak do wstrzykiwania brzeczki ogarniał i szybciej startował niż Spring. To już było ile z 10?
Tak, to może być Max. Drugi z był tylko kontenerem zależności i dependency injection.
No tak, ale taki przedsmak może tego, może trochę tak, może trochę. Natomiast Micronaut i Quarkus to są frameworki, które właśnie, tak jak wspomniałem, starają się bardzo dużo skompilować na compile time, tak żeby już w runtime’ie były gotowe klasy, które wszystkie nasze rzeczy niezbędne i potrzebne mają, więc one też mają. Generalnie jeśli przesiadamy się ze Springa, użycie jest bardzo podobne. Mamy również REST-owe kontrolery robione za pomocą adnotacji. Mamy również adnotacje. Mamy deklaratywne. Natomiast nie można wszystkich tych adnotacji używać standardowych, bo Spring wiadomo ma swoje ulubione, ale od pewnego momentu już nawet Spring pozwolili.
Tak, tak, generalnie tak. Część ma swoje odpowiedniki w konkretnym frameworku, ale inne na przykład są te standardowe. Generalnie jeśli mamy taką zwykłą małą appkę Springową, robiącą niewielką rzecz i ma ona być serverlessowa, to raczej nie powinno zabraknąć ficzerów. Jest też wsparcie dla Persistance, więc i ja to zrobiłem. Troszkę tam inaczej podchodzą, ale generalnie też da się to zrobić i da się generować encje i zapytania z tym związane. Część zapytań SQL-owych będzie też wygenerowanych w compile time. Te zapewne, które nie mają jakiś parametrów specyficznych, więc jak najwięcej rzeczy takie komórki generują.
Pamiętajmy i dzięki temu ten start-up time w porównaniu do Springa znacznie, znacznie się uprościł. Nawet twórcy Micronauta, po jednym z pierwszych rodziców zauważyli, że następny, czyli Spring Boota też nagle przyspieszył jakoś magicznie i nic nie podejrzewają, że może tutaj przypadek. Nastąpiła pewna pewne zapożyczenia.
Twórczą inspiracją to nazywamy inspiracja.
Tak, właśnie tego szukałem. Zresztą Quarkus też wyszedł. W Micronautcie też zdaje się na tej idei troszkę. Zakomunikował, że to ten pierwszy miał najgorzej jak ten pierwszy, więc. Więc tak, jeśli mamy jakiś mózg z małego sklepiku, który może robi niewiele mikro serwisów, więc powinien być mały. Więc tutaj możemy spokojnie rozważyć alternatywę czy to Micronaut czy Quarkus powinny sobie spokojnie dać radę. Ja akurat robiłem jakąś aplikację na Quarkusie produkcyjnie i dość miło wspominam nawet ten framework. Nie brakowało mi szczerze mówiąc użycia Springa. Całkiem fajnie. Wszystkie rzeczy, których potrzebowaliśmy zrobić, super dało się zrobić w Quarkusie. Rzeczywiście było tak.
Metryki i doświadczenia
Jak faktycznie na produkcji taka lambda powstawała, jak szybko mieliście jakieś metryki, to tutaj przytoczę, bo za bardzo tego nie mierzyliśmy. Zresztą w tym projekcie akurat to wydajnościowe były akurat przesłanką do wybrania Quarkusa. Bardziej chyba takie względy: “o jakiś fajny framework, więc użyjemy tego”, bo Spring już się wszystkim znudził, więc chyba tutaj bardziej o ulubione.
No tak, ale jak widać, zespół zdaje się myślał podobnie. Nie sprawiło to problemów, że tak powiem. Raczej nikt nie mówił, że szkoda, że nie wzięliśmy Springa, bo nie da się tego czy tego. Nie. Tutaj wszystko dało się zrobić.
Tutaj pomaga pewnie założenie, że jeżeli to jest lambda, to jest to niewielkie, bo też nie napchane tam nie wiadomo ile tego. Cała ta aplikacja była taka większa niż przysłowiowa lambda. To było w sumie pełnoprawna aplikacja. I również.
Tylko Quarkus całkiem sprawnie i sprawnie tam się sprawdził.
Więc tak jak… Ale ona to tak wstawała, że tak dopytam, bo pełnoprawna, to zachowywała się jak lambda, czyli wstawała sobie na request?
To była taka normalna webowa aplikacja. Nie na serwer żaden tam.
Normalna, normalna aplikacja. Tutaj już można spokojnie sobie jakieś podpiąć mierzyć, nawet na piechotę. Tak, bo nie ma wymogu, że Micronaut to są stricte frameworki. Nie, nie, to są normalne. Tylko aż się prosi, żeby używać ich w serverlessie. Tak, tak, tylko właśnie ze specyficznym jakby targetem stref czasowych ze względu na ich szybki start i brak tego…
No i pewnie też ten narzut pamięci. Już tego pod print nie będzie tak cały czas.
Na pewno tak, dostawcy na pewno tak, bo tutaj mamy znacznie mniej, albo wręcz w ogóle brak operacji skanowania jako spam, albo ładowania do pamięci, więc stąd wynika też to, z braku tych operacji, które są nagminne zasobów.
Co jeśli mamy, że nie tylko w Springu one są, po prostu są zasobem w Javie i tylko takie stąd się da, bo rzeczy, które też poprzednio w garażach właśnie… Dokładnie. Tutaj mamy przynajmniej te chmurki dostępne od teraz, bo wiadomo, Project Valhalla czy Project Leyden to są rzeczy, które pewnie będą dostępne dopiero za pewnie kilka lat, jednak raczej niż kilka miesięcy. To trzeba sobie jasno powiedzieć. Więc jeśli poszukujemy jakiegoś rozwiązania na teraz i chcemy przyspieszyć jakieś nasze projekty na teraz, to Micronaut albo Quarkus mogą być fajną alternatywą, którą możemy przetestować już teraz, niż czekać na jakieś nowe projekty.
Konfiguracja i optymalizacja w Javie
Tym bardziej, że pewnie jakaś tam krzywa uczenia ze względu na podobieństwa do Springa. Ogólnie podobieństwa do wszystkiego. Opowiem o tym, co posiadam. Naprawdę bardzo przyjemnie się je czyta. Jeśli chodzi o podobieństwo do Springa, to Micronaut jest chyba ciut bardziej podobny i może delikatnie lepiej zintegrowany ze Springiem, ale generalnie oba są bardzo czytelne. Trzeba pewnych konceptów gdzieś tam sobie doczytać w tej dokumentacji, ale nie ma to, nie ma to większego problemu. Wszystkie są nowe rzeczy, jak to fajnie opisane, więc tutaj nie ma problemu. Wciąż oba są oczywiście rozwijane i da się znaleźć sporo materiałów czy prezentacji na te oba tematy. Są tacy porównujący te dwa frameworki, też da się tym… Da się, da się porównać i zobaczyć co, jakieś benchmarki się pojawiają.
Jakieś były. Już chyba sobie teraz nie przypomnę, więc nie będę tutaj ich przytaczać.
Albo Ty pamiętasz? Zależy od jakichś konkretnych przypadków użycia i tego, jaki mamy profil aplikacji, więc też sprawdzić może jakiś mały koncept zrobić, na przykład, w jednym czy drugim, albo nawet w obu. Bo jednak start aplikacji jakieś tam na szybko to nie jest jakoś tam zbyt skomplikowane. Micronaut ma podobny finish laser jak Spring, czyli możemy sobie na stronce wyklikać paczki, które sobie chcemy zrobić i to obie strony się inspirują. Wygeneruje nam ZIP-a. Micronaut ma konsolowy interfejs, w sensie z filmikami, gdzie można, bo to paczki również klikasz. Więc projekty możemy sobie bezboleśnie stworzyć dość łatwo i sprawdzić sobie, jak oba rozwiązania się sprawdzają.
Brzmi to bardzo kusząco i aż grzech teraz nie skorzystać. Ja miałem w ogóle hejtować tą Javę, ale tak słucham, słucham, słucham, myślę: “Kurka wodna, no właśnie, to tam, gdzie jestem teraz w C++, to nie ma takich”.
Nie ma takich.
No właśnie. To było celem całej tej opowieści, żeby pokazać, że jednak w Javie ostatnio dzieje się dość dużo. Jednym z tych ostatnich już, ostatnim punktem i muszę powiedzieć ficzerem, który, który, który trafi, może niedługo do tej firemki, jest coś, co się nazywa “Expose”. To jest rzecz zapowiedziana bardzo niedawno i generalnie ma to już głównie chodzić o konfigurację. Na szczęście może to się objawi szybciej niż dalej. To generalnie ma sprawić, że to profile mają sprawić, że konfiguracja będzie dobrana. Konfiguracja mamy na myśli rozmiar heap’a, dostępność procesora oraz wielkość wewnętrznych wątków w Javie. I ta konfiguracja ma być dobrana.
Wzorzec.
Od tego czy JVM jest uruchomiony w trybie “short”, czyli właśnie na systemie, który sam sobie działa i działają z nim czasem jakieś inne aplikacje, czy w trybie kontenerów Docker’a. Bo według ostatnich raportów wychodzi na to, że Java jest w 70 procentach przypadków odpalana w kontenerach. Więc jeśli jest odpalana w kontenerze, to de facto jest, można powiedzieć, jedynym procesem albo jednym z najważniejszych. Więc możemy spokojnie przydzielić jej właściwie całą dostępną pamięć. Wszystko, całe wszystko. Bo ten kontener to właściwie jest potrawka. Więc możemy…
Tym bardziej, że od jedenastki już weszły możliwości konfiguracyjne. Zresztą w ogóle weszła taka jakby wewnętrzna inteligencja tej konfiguracji, gdzie JVM już rozpoznaje, ile ma tak naprawdę zasobów. Fizycznych tam jeszcze poniżej jedenastki, jeszcze tego nie umiała, ale tutaj już, na przykład, potrafi skumać, że…
Deweloperzy to są rzeczy, których bardzo często się po prostu nie ustawia, nie sprawdza i zostawia się te kwotowe wartości, bo jakby nie patrzeć.
Takie proste tuning w kontekście parametrów i przydzielenia większej ilości zasobu był ostrożny, bo niekoniecznie musi to być prosty tuning. Te frontowe parametry to jednak one będą miały sens i sam ten mechanizm auto konfiguracji Javy, który pozwala w locie w ogóle jak wiemy dopasować te parametry właśnie chociażby na podstawie tego, gdzie się znajduje, w jakim środowisku. To właśnie ten ficzer, który wszedł już od jedenastki w górę, to to już jest bardzo duże ułatwienie do poprawnego albo bardziej poprawnego niż było skonfigurowania wcześniej.
Podsumowanie i dalsze kroki
Poznawania przez sieć się nie robiło. Można powiedzieć.
Tak. I wcześniej taka dawka w Javie 8 odpalona gdzieś tam na Dockerze w ilości iluś tam bloków na danej platformie. Po prostu ulokowała całą dostępną pamięć w każdym kontenerze, na przykład, co się szybko objawiało jakimś OutOfMemoryError. Szybko, jak szybko, ale w którymś momencie mogło się objawić OutOfMemoryError. W takich poszczególnych instancjach nie szło nic z tym zrobić za bardzo. Trzeba było kombinować na poziomie parametrów uruchomieniowych.
Tak. Tutaj ta inicjatywa jeszcze jest w dość wczesnej fazie, więc brak może jeszcze konkretnych szczegółów, ale nie ma co ukrywać, że nacisk na pewno będzie na Javę uruchamianą w kontenerach, generalnie w chmurze. Więc po raz kolejny jest szansa, że dostaniemy jakiegoś boosta, jakiegoś dobrego kopa dla Javy w naszym serverlessie.
Skompiluje się go i będzie.
Tak więc to są chyba takie główne, główne projekty i zmiany, które może nie za rogiem, ale gdzieś tam w najbliższym czasie są. Za skrzyżowaniem, za skrzyżowaniem, tym następnym skrzyżowaniem. No chyba, że chcemy coś od zaraz, to możemy sprawdzić frameworki, o których tu wspominaliśmy, czyli Quarkus i Micronaut, albo poczekać na to, co przyniosą nowe wersje. Tak czy siak, jedno i drugie wygląda obiecująco. I za bardzo hejtować tutaj już nie wypada, bo jak się tak wróci pamięcią do tego, jak to drzewiej bywało, to płacz i zgrzytanie dziąseł. Można by powiedzieć, że w tak nowoczesnych wersjach Javy, to już właśnie ósemka, jedenastka. One już przyniosły jakościową różnicę. Bardzo dużo, nie tylko na poziomie modelu programistycznego Javy, ale też i na poziomie samej platformy, czyli tego, co tam się wykonuje. I tutaj pewnie powoli, po omówieniu tychże właśnie wspaniałych cacek, byśmy musieli
musieli przejść do już takich troszkę wnętrzności tego całego wykonywania. Co tam się właściwie w tym runtimie chciałoby dziać i chcielibyśmy już to wydajność pewnie jakoś gdzieś zobaczyć. Nie w sensie, jak ją można zmierzyć, bo żeby ją zobaczyć, to trzeba zmierzyć to najpierw, nie? Czyli trzeba jakieś tam benchmarki sobie porobić, a to nie jest takie hop-siup.
Następny odcinek
To już będzie w następnym odcinku. To już pewnie w następnym odcinku. No i też pewnie powiemy o tym, o czym tutaj nie zdążyliśmy, że mimo że tego typu pamięć dysku nawet nam przerastało przez dziesięciolecia, to mimo wszystko nie samą Javą żyje komputer. Jakby tak na to popatrzeć.
Czyli jeżeli chcielibyśmy sobie coś uszczknąć na lokalnej maszynie, na której kodujemy, to to pewnie pojawiają się jakieś możliwości, ale jakbyśmy chcieli przyjrzeć się takiemu środowisku serwerowemu, gdzieś tam, gdzie te kontenery nasze hulają, to okaże się, że tych procesów tam jest całkiem dużo.
Tam jest pewnie też dużo wątków sprzętowych, nawet nie, bo są takie procesory naprawdę potężne, po kilkadziesiąt rdzeni, tylko że drogie jak nieszczęście. I one tam są srodze wirtualne, więc tam po prostu nie tylko wątki, ale i procesy na tym wszystkim hulają i my dostajemy którąś tam warstwę abstrakcji.
W tej warstwie abstrakcji dopiero są te nasze niby sprzętowe rzeczy, ale no, oprócz naszego procesu Javy do JVM-a, który dzieli się na wątki, my jeszcze sobie dołożymy miliard tych wątków leciutkich. No i jeszcze są inne procesy w tym samym systemie i one też mają ok, nie uciągnie.
Dobre praktyki i przyszłość
No wiadomo, nie mówię, że nie. Ale my to sobie zmierzymy. Może kiedyś zmierzymy.
Brzmi zachęcająco.
Przyjrzymy się pewnie też może na początku teorii. W ogóle jak można by pisać takie aplikacje, a nawet wcześniej jeszcze jak pisać programy w ogóle i z czego je konstruować, żeby jednak nie zabijały tego, cokolwiek to mają pod spodem służyć. To będzie nie wiem, czy to po prostu już fizyczny sprzęt.
Dobre praktyki to jednak podstawa zawsze, niezależnie od ilości RAMu czy ilości wirtualnych wątków.
Dokładnie. No to pewnie w następnym odcinku od tego zaczniemy.
Brzmi interesująco!
Dzięki Wojtek za przedstawienie tych wszystkich nowinek.
Dzięki Michał. Do następnego odcinka.
Do następnego. Cześć, cześć.