Po okresie newsów, ogłoszeń i kolejnych releasów, myślę że warto siąść spokojnie i zatopić w ciekawych case study i esejach. A że w ostatnich tygodniach pojawiły się trzy, to o one właśnie wypełnią naszą dzisiejszą edycje.
1. Jaka przyszłość czeka Scale?
Mamy na pokładzie jakichś fanów Scali? Pytam nie bez powodu – niedawno bowiem pojawił się ciekawy tekst Scala’s Future, w którym Alexandru Nedelcu próbuje ocenić, na ile język ma przyszłość, a także dostarcza przemyślanych refleksji na temat ewolucji i obecnego stanu różnych języków programowania, ze szczególnym uwzględnieniem właśnie Scali.
Autor zaczyna od tematu, który jeszcze niedawno wydawał się jedynie opowieścią do straszenia programistów przy ognisku, a dziś coraz częściej zaczyna być przywoływany jako punkt wyjścia do refleksji nad dzisiejszym stanem branży – od wspomnienia trudnych czasów bańki internetowej, szczególnie w Rumunii z której pochodzi. Okazuje się, że już wtedy pojawił się duży czasowy spadek popularności Javy w tym okresie, ta jednak okazała się bardzo odporna na rynkowe fluktuacje.
Ten historyczny kontekst stanowi tło do dyskusji na temat pęknięcia „bańki technologicznej” w 2023 roku. Choć pewnie można to „pęknięcie” potraktować jeszcze z pewnym przymróżeniem oka, to już dzisiaj charakteryzuje się nie tylko znacznymi zwolnieniami w branży technologicznej, ale co ciekawe także spadkiem aktywności online w większości języków programowania. Autor zauważa, jak złudne może być postrzegania popularności języków, używając Rusta i Kotlina jako przykładów – okazuje się bowiem, że wbrew obiegowej opinii i wizerunku czających się za rogiem drapieżnych tygrysów, ich rzeczywisty wzrost popularności nieco się zatrzymał. Alexander podkreśla też znaczenie twardych faktów nad nadmiernym entuzjazmem, a języki mają swoją niszę – taki choćby wspomniany już Rust to rywal C++ i nie jest bezpośrednim konkurentem dla języków z automatycznym zarządzaniem pamięcią, takimi jak Java i Scali.
W samej dyskusji na temat Scali, autor podkreśla zaś jej silną społeczność i różnorodne ekosystemy, zwracając uwagę na bardzo produktywną naturę community pomimo jego stosunkowo mniejszego rozmiaru. Post omawia również podróż Pythona i jego długą, trudną migrację do Pythona 3. Pomimo wielu przeszkód i obaw, Python to teraz według wielu statystyk najpopularniejszy język świata, nie biorący jeńców w takich obszarach jak choćby ML. Ten Pythona nie pojawia się tam przez przypadek – Alexander wysnuwa paralele między nim, a obecną trajektorią Scali, sugerując, że choć migracja całej społeczności do Scali 3.0 zajmie czas i z pewnością będzie trudna, to jest to dobry kierunek. Dzięki temu, że Scala 3.0 to obiektywnie lepszy język od wersji 2.0, po bolesnym okresie tranzycji ekosystem będzie w znacznie lepszej pozycji do walki o serca programistów z całego świata.
A jak to wygląda u Was? Wierzycie w to, że Scale czeka świetlana przyszłość? A może właśnie przepisujecie się na Scalę 3.0?
Zainstaluj teraz i czytaj tylko dobre teksty!
2. Jak Uber radzi sobie z setkami terabajtów logów?
Tym razem trochę naciągnę, ale rzadko mam okazje dzielić się fajnym case z Ubera. Zawsze lubiłem ich publikacje, bo często zamiast skupiać się na dosyć abstrakcyjnych tematach architektonicznych (patrzę się na Was, Netflix) schodzą na rzeczy bardziej przyziemne, ale dalej będące kawałkiem ciekawej inżynierii. Nie inaczej jest w wypadku Reducing Logging Cost by Two Orders of Magnitude using CLP. Tekst ma już ponad rok, ale ostatnimi czasy na nowo wypłynął w socialkach, a od tego czasu nie zestarzał się ani o jotę.
Dlaczego coś takiego trafia do Javowego Newslettera? Artykuł omawia bowiem, w jaki sposób Uber znacząco obniżył koszty logowania poprzez integrację narzędzia Compressed Log Processor (CLP) z biblioteką Log4j w ichniejszej platformie przetwarzania danych. Jak łatwo się domyśleć, wraz z rozwojem działalności Ubera objętość logowanych danych dramatycznie wzrosła, prowadząc do wysokich kosztów i konieczności szybkiego rotowania logów. Integracja CLP umożliwiła osiągnięcie współczynnika kompresji na poziomie 169x, znacznie obniżając wymagania dotyczące przechowywania, pamięci i przepustowości sieci. Ta poprawka pozwoliła Uberowi na retencje logów przez dłuższy okres, umożliwiając wgląd w historyczne dane i efektywniejsze przeszukiwaniu logów bez konieczności dekompresji.
Tekst pozwala też przyjrzeć się bliżej rozmiarowi samego Ubera – przed wprowadzeniem poprawki firma generowała do 200 TB logów (!) w peaku. Z tego względu standardowe, istniejące narzędzia do zarządzania logami, takie jak Elasticsearch i ClickHouse, były albo zbyt kosztowne, albo niedopasowane do efektywnego obsługiwania skali logów Ubera. Z tekstu dowiemy się, że przy tej skali okazuje się, że nawet takie wydawałoby się pomijalne przez większość z nas rzeczy, jak zapisywania plików logów małymi porcjami w czasie powodowała przedwczesne zużycie SSD.
Zainstaluj teraz i czytaj tylko dobre teksty!
3. Użycie Wirtualnych Wątków nie zawsze jest trywialne? Kto by się spodziewał…
A na koniec mam dla Was ciekawy przykład użycia Virtual Threads w realnych, nietrywialnych przypadkach. Autorem publikacji How we switched to Java 21 virtual threads and got a deadlock in TPC-C for PostgreSQL jest Evgeniy Ivanov, pracujący nad bazą danych YDB. Jej twórcy pracują aktualnie nad kompatybilnością PostgreSQL z YDB, głównie ze względu na duży popyt ze strony użytkowników PostgreSQL. Podczas tego procesu pracowali nad implementacją benchmarków porównawczych, co sprawiło, że natknęli się na nieoczekiwane problemy.
Post omawia wyzwania i rozwiązania napotkane podczas implementacji TPC-C (Transaction Processing Performance Council Benchmark C) dla PostgreSQL przy użyciu wirtualnych wątków Java 21. TPC-C to standardowy test wydajnościowy dla systemów baz danych, opracowany przez Transaction Processing Performance Council (TPC) i pozwalający ocenić wydajność przetwarzania tranzakcji. Jak to z benchmarkami bywa, ich implementacja bywa „tricky”, wymagają bowiem często niestandardowych technik. Tak było i w tym przypadku – początkowo autorzy napotkali bowiem problem z ograniczeniem współbieżności z powodu tworzenia zbyt wielu fizycznych wątków w oryginalnej używanej przez nich implementacji TPC-C. Aby temu zaradzić, postanowili użyć wirtualnych wątków z JDK 21, chcąc bardziej efektywne poradzić sobie z dużą współbieżnością. Jednak szybko odkryli, że wirtualne wątki mogą prowadzić do nieprzewidywalnych zakleszczeń, zwłaszcza gdy występują głęboko w używanych bibliotekach.
Przykładowo, autor napotkał się na sytuację zakleszczenia w swojej implementacji TPC-C dla PostgreSQL przy użyciu c3p0 – biblioteka do pulowania połączeń JDBC w sytuacji wysokiej współbieżności, z obsługą buforowania i ponownego wykorzystania PreparedStatements
do pulowania połączeń. Aby rozwiązać problem, zaczęli schodzić coraz niżej i odkryli, że wirtualne wątki oczekujące na sesję blokują ich wątek nośny. Rozwiązaniem było użycie java.util.concurrent.Semaphore
do opakowania połączenia, co zapobiegało blokowaniu wewnątrz c3p0 i umożliwiło efektywne używanie wirtualnych wątków. Ten przykład pokazuje złożoność implementacji wirtualnych wątków i znaczenie zrozumienia, jak wchodzą one w interakcje z innymi komponentami w systemie. Okazuje się, że problemy mogą trafić z nieoczekiwanych miejsc, a nawet jeśli my sami użyjemy Wirtualnych Wątków w prawidłowy sposób, to nigdy nie możemy ufać, że używane przez nas zależności nie sprawią nam niespodzianki.
Artykuł jest całkiem ciekawym źródłem dla rozważających przejście na wirtualne wątki, ponieważ dotyka nioczywistych niuansów, które często giną pod wysypem Hello World. Post (a także wcześniejsze publikacje YDB) zawiera też sporo inny ciekawych informacji dla interesujących się współbieżnością baz danych. Jeżeli kiedykolwiek interesował Was temat – bardzo polecam.