Dzisiaj Release Radar, Code Reflection oraz podsumowanie akcji 1BRC. Plus trochę filozoforowania z mojej strony.
1. 1BRC, czyli po co nam Moonshoty?
Ground Control to Major Tom
Ground Control to Major Tom
Take your protein pills. And put your helmet on…
Zaczniemy sobie dzisiaj od książki – otóż aktualnie na moim czytniku gości wspaniałe „Chip Wars”, czyli książka przedstawiająca kulisy powstania branży mikroprocesorów. To co jest w niej fascynujące to fakt, że autorzy skupiają się w niej nie na aspekcie technologicznym (przez ten w zasadzie się prześlizgują), ale przedstawiają realia ekonomiczno-społeczne, które potrafią zmienić nowinkę techniczną w realną rewolucje. Czasem potrzeba po prostu trochę sprzyjających okoliczności, a zwłaszcza realnych wyzwań, które zmuszą inteligentnych inżynierów do przesuwania istniejących granic tego, na co technologia pozwala. Mamy na to nawet w branży termin – tak zwane „moonshotów”.
Ogólnie książkę bardzo polecam, kapitalnie się ją czyta.
Termin „moonshot” w kontekście technologii i innowacji wywodzi się z monumentalnego osiągnięcia misji Apollo 11, która zakończyła się pierwszym lądowaniem człowieka na Księżycu w 1969 roku. To historyczne wydarzenie stało się symbolem ambitnych, eksploracyjnych i przełomowych projektów, mających na celu osiągnięcie tego, co wcześniej uważano za niemożliwe. Istota moonshot polega na skupieniu się na wielkich, śmiałych celach; chodzi o podejmowanie ogromnych wyzwań bez gwarantowanego wyniku, wykorzystując przełomowe technologie i innowacyjne myślenie, aby przesuwać granice tego, co jest osiągalne.
Dziedzictwo lądowania na Księżycu wykracza daleko poza samo historyczne wydarzenie, wpływając na liczne aspekty naszego codziennego życia. Technologie opracowane dla potrzeb eksploracji kosmosu doprowadziły do powstania wielu pochodnych korzyści dla społeczeństwa, od postępów w telekomunikacji i informatyce, po nauki o materiałach i technologię medyczną. Na przykład zminiaturyzowana elektronika (stąd początkowe nawiązanie do „Chip Wars”), początkowo rozwijana dla misji kosmicznych, utorowała drogę dla malutkich, mocarnych urządzeń komputerowych, których używamy każdego dnia. Dążąc do pozornie nieosiągalnych celów, projekty moonshot nie tylko rozszerzają nasze możliwości technologiczne, ale także inspirują przyszłe pokolenia do kontynuowania eksploracji i przesuwania granic tego, co jest możliwe.
Dlatego też pozostaje chyba ostatnim człowiekiem, który kibicuje Mecie w ich pracach nad Metaversum. Metaverse (jak bardzo szalone się wydaje) ma potencjał do zrewolucjonizowania sposobu, w jaki żyjemy i pracujemy. Wyobraźmy sobie wirtualne spotkania z klientami, bez względu na ich lokalizację (bez całego zmęczenia związanego z pozostawaniem w jednym pokoju cały dzień i przeskakiwania z pokoju do pokoju), czy zwiedzanie muzeów i galerii sztuki bez wychodzenia z domu. To są fajne koncepty, jeśli nie skupimy się tylko i wyłącznie na ryzykach (choć o nich też nie można zapominać). A ilość technologii, które będą musiały powstać, żeby to rzeczywiście zadziałało jest wręcz niesamowita – i te małe rewolucje już się dzieją. Wystarczy spojrzeć, jak przystępnie wycenione w stosunku do możliwości są ichniejsze google Meta Quest 3. Lekcją, którą wyciągnąć można ze wspomnianego Chip Wars jest to, że to właśnie masowość jest tym co sprawia, że rozwój technologii idzie do przodu. I dalej wierze w VR, mimo że cały świat obecnie robi sobie jaja z Apple Vision Pro.
Powyższy obrazek ukradzione od Kena Kousena i jego newslettera Tales of the Jar Side 😃
No dobra, ale do brzegu, bo to JVM Weekly, a ja tutaj historię życia opowiadam. A wszystko zmierza ku temu, że w zeszły czwartek doszło do ogłoszenia wyników One Billion Row Challenge, które dla mnie spełnia masę kryteriów opisywanych powyżej moonshotów. Mamy ambitny cel, świetne przywództwo projektu ze strony Gunnara Morlinga oraz setki najlepszych programistów Javy próbujących przesuwać kolejne granice tego, co uważaliśmy za możliwe jeśli chodzi o wydajność aplikacji napisanych w Javie. Ostatecznie udało się zejść grubo poniżej dwóch sekund, a to już są wartości wręcz kosmiczne. Jestem pewien, że wyniki rywalizacji będą wykorzystane podczas planowania dalszego rozwoju JDK.
Bardzo ciekawym jest to, że większość najlepszych rozwiązań wykorzystuje GraalVM Native Images oraz sun.misc.Unsafe
. To pierwsze jest świetnym case study dla tych, którzy szukali dowodów na wydajność GraalVM – mnie osobiście już zaczęło się to przydawać przy rozmowach z klientami. Jeśli zaś chodzi o sun.misc.Unsafe
, to po tym jak udowodniło ono swoją przydatność w naszym małym „moonshotcie”, piłeczka stoi po stronie twórców OpenJDK. Autorzy JEP draft: Deprecate Memory-Access Methods in sun.misc.Unsafe for Removal mają pewnie teraz ciężki orzech do zgryzienia.
Jeżeli jesteście ciekawi, jaka czarna magia została wykorzystana, to Nicolai Parlog nagrał webinar z twórcami najwydajniejszych rozwiązań. Prawdziwa piguła wiedzy dla każdego, kto chciałby poznać najbardziej obskurne detale wydajności JVM.
Osobiście najbardziej lubię fragment, w którym Thomas tłumaczy, dlaczego kompilator AoT Graala / JIT + FMM nie są w stanie automatycznie osiągnąć wydajności ręcznego użycia sun.misc.Unsafe
. Ale całość jest totalnie warta obejrzenia – aż przyjemnie się patrzy jak wszyscy się dobrze bawią na tym streamie.
Zainstaluj teraz i czytaj tylko dobre teksty!
2. Praktycznie o Project Babylon: Automatyczna różniczkowanie za pomocą refleksji kodu
Widać, że 2024 ruszył z kopyta. Dwa tygodnie temu pisałem o nowych Design Docach od Briana Goetza dotyczących konceptu Deconstructors, teraz przyszedł czas na pierwszy oficjalny tekst opisujący możliwości użycia Project Babylon.
Artykuł Automatic differentiation of Java code using Code Reflection autorstwa Paula Sandoza omawia koncepcję i implementację automatycznego różniczkowania metod Java reprezentujących funkcje matematyczne za pomocą Code Reflection. Poprzez uzyskanie symbolicznej reprezentacji metody program może zastosować reguły różniczkowania do wygenerowania metody różniczkowej. W bardzo uproszczony sposób całość można sprowadzić do następujących punktów (kilka kroków z artykułu pominąłem dla klarowności):
Metoda Java, którą chcemy zróżniczkować, jest oznaczana za pomocą adnotacji @CodeReflection
.
@CodeReflection
static double f(double x, double y) {
return x * (-Math.sin(x * y) + y) * 4.0d;
}
W czasie kompilacji dla oznaczonej metody tworzony jest Code Model, który jest symboliczną reprezentacją tej metody, a następnie używając refleksji Java, uzyskujemy dostęp do modelu kodu oznaczonej metody, który przyjmuje formę drzewa.
Method fm = T.class.getDeclaredMethod("f", double.class, double.class);
Optional<CoreOps.FuncOp> o = fm.getCodeModel();
CoreOps.FuncOp fcm = o.orElseThrow();
Potem następuje sam proces różniczkowania (nie będę tego przyklejał, ciężka matma – zaglądnijcie do oryginalnego artykułu, a na jego podstawie zróżniczkowanych operacji tworzony jest nowy model kodu, który reprezentuje pochodną metody. Zróżniczkowany model kodu jest kompilowany do bajtkodu Java, a skompilowany bajtkod może być wykonywany, aby obliczyć wartości pochodnych.
Efektem jest binarny ekwiwalent poniższych funkcji:
static double df_dx(double x, double y) {
return (-Math.sin(x * y) + y - x * Math.cos(x * y) * y) * 4.0d;
}
static double df_dy(double x, double y) {
return x * (1 - Math.cos(x * y) * x) * 4.0d;
}
Mamy do czynienia z relatywnie prostym do zrozumienia, ale nie tak bardzo oderwanym od rzeczywistości przykładem. Artykuł podkreśla znaczenie automatycznego różniczkowania w uczeniu maszynowym, gdzie modele matematyczne są trenowane przez tak zwane „algorytmy gradientu prostego” wymagające obliczania gradientów. Proces ręcznego różniczkowania jest podatny na błędy i żmudny, szczególnie dla skomplikowanych funkcji, co czyni automatyczne różniczkowanie cennym narzędziem dla programistów i pokazem tego, jakie nowe możliwości już niedługo dostaniemy jako programiści. Jak pisałem w ostatniej edycji, Project Babylon szybko wskoczył do mojej topki najciekawszych projektów dziejących się w ramach JDK i obiecuje, że będę śledził wszystkich nowych ogłoszeń z nim związanych.
3. Release Radar
Pkl
A dzisiejszy Release Radar zaczynamy od nietypowego – nowego języka programowania(!) do konfiguracji (!!) od Apple (!!!). Nietypowo jak na JVM Weekly, prawda? Ale nie martwcie się, zaraz wszystko się wyjaśni.
Pkl (Pickle) to język programowania zaprojektowany specjalnie do tworzenia konfiguracji, adresując ograniczenia statycznych języków konfiguracyjnych takich jak JSON czy YAML które często nie radzą sobie z złożonością i ekspresyjnością. Pkl bierze za cel połączyć w sobie prostotę i deklaratywność formatów statycznych z elastycznością języków programowania ogólnego przeznaczenia. To pozwala Pkl oferować klasy, funkcje, warunki i pętle, umożliwiając tworzenie bardziej zaawansowanych i reużywalnych skryptów konfiguracyjnych.
Poniżej przykład umożliwiający stworzenie 4 instancji bazy danych
module Application
class Database {
username: String
password: String
port: UInt16
}
hidden db: Application.Database = new {
username = "admin"
password = read("env:DATABASE_PASSWORD")
}
sidecars {
for (offset in List(0, 1, 2)) {
(db) {
port = 6000 + offset
}
}
}
Co wygeneruje nam poniższego JSON-a:
{
"sidecars": [
{
"username": "admin",
"password": "hunter2",
"port": 6000,
},
{
"username": "admin",
"password": "hunter2",
"port": 6001,
},
{
"username": "admin",
"password": "hunter2",
"port": 6002,
}
]
}
Co więcej, Pkl jest zaprojektowany, by być skalowalnym, bezpiecznym i przyjemnym w pisaniu, poprzez posiadanie wbudowanych mechanizmów walidacji.
Czyli pozostaje kolejnym narzędziem, którego istnienie pozwala nam jeszcze bardziej nienawidzić YAML-a.
No dobra, ale wróćmy do oryginalnie postawionego pytania – skąd pojawienie się narzędzia w dzisiejszym przeglądzie? Wynika to z technologii, która została użyta do tworzenia CLI towarzyszącego językowi. O ile coraz częściej do podobnych zastosowań używa się dzisiaj Rusta, to w tym przypadku całość została napisana w Javie, i dystrybuowana jest jako binarny natywny obraz GraalVM. Nie jest to często spotykany format, a Pkl pokazuje, że technologia posiada zastosowanie nie tylko na serwerze, ale i w aplikacjach CLI.
Może jednak 2024 to nie będzie rok Rusta?
Zainstaluj teraz i czytaj tylko dobre teksty!
CheerpJ 3.0
CheerpJ to implementacja JVM oparta o WebAssembly, która umożliwia uruchamianie aplikacji Java bezpośrednio w przeglądarce, bez potrzeby instalowania wtyczek czy samej Javy. Dzięki wsparciu pełnego zbioru funkcjonalności OpenJDK, pozwala na odtworzenie dużych, niezmodyfikowanych aplikacji i bibliotek Javowych w większości nowoczesnych przeglądarek. CheerpJ obsługuje też stare aplety Java i aplikacje Java Web Start, o czym ostatnio miałem okazje pisać przy okazji wskrzeszenia starej przeglądarkowe gry Dragon Court.
CheerpJ 3.0, najnowsza „duża” wersja, jest napisana w zasadzie od nowa, korzystając z siedmioletnich doświadczeń pracy nad innymi projektami opartymi na WebAssembly, takich jak CheerpX (odpowiednika CheerpJ dla Flasha). „Trójeczka” poprawia wydajność, zwłaszcza czas uruchamiania, poprzez potrzeby usunięcie kompilacji Ahead-Of-Time przy pierwszym uruchomieniu. Oferuje WebAssembly JVM i kompilator JIT dla bajtkodu Java, a także zwirtualizowaną warstwę systemową dla systemów plików i sieci.
CheerpJ 3.0 obsługuje na ten moment tylko Javę 8, ale w dalszej części roku już jest zapowiedziane wsparcie dla Javy 11. Aby zademonstrować jej możliwości, twórcy użyli nic innego jak… Minecrafta, umożliwiając jego uruchomienie właśnie w oknie przeglądarki.
To teraz czekam na osiągnięcie Metacircularity poprzez napisanie JVM w Minecrafcie. Hardware powoli się tworzy.
Liberica JDK 21 – RISC-V Edition
Liberia lubuje się w nietypowych dystrybucjach JDK. Mieliśmy już w zeszłym roku Liberica JDK Performance Edition – wariant JDK 11 z poprawkami wydajnościowymi, a teraz przychodzi wariant JDK działający natywnie na procesorach w architekturze RISC-V.
Coraz popularniejsze, głównie ze względu na swój otwarty charakter, RISC-V nie jest wbrew pozorom procesorem, a raczej modelem programowym procesora (z angielskiego ISA) opartego o filozofię dostarczania ściśle wyspecjalizowanego zestawu instrukcji (reduced instruction set computer – RISC właśnie). Cytując Wikipedię:
W kontraście do większości ISA, RISC-V może być swobodnie używany w dowolnym celu, umożliwiając każdemu projektowanie, produkcję i sprzedaż czipów i oprogramowania RISC-V. Chociaż nie jest pierwszą otwartą architekturą ISA ma duże znaczenie, ponieważ został zaprojektowany z myślą o nowoczesnych skomputeryzowanych urządzeniach, takich jak ogromne chmury obliczeniowe, wysokiej klasy telefony komórkowe i najmniejsze systemy wbudowane.
Wsparcie dla RISC-V pojawiło się już przy okazji JDK 19, ale z tego co się orientuje Liberica jest pierwszym vendorem, który zapewnił łatwą do pobrania dystrybucje. Jeśli się mylę, poprawcie mnie proszę w komentarzach – też chętnie się czegoś nowego dowiem 🙂
Quarkus 3.7
Najnowszy Quarkus 3.7 nie tylko pobija wymaganą wersję Javy do JDK 17, ale także rozpoczyna proces porządkowania nazewnictwa RESTEasy Reactive. Ta wersja usprawnia też wsparcie dla Hibernate, aktualizując Quarkusa do najnowszych stabilnych wersji popularnego Javowevego ORM oraz wprowadzając endpoint do zarządzania Hibernate Search. Pozbywa się także wymogu korzystania z przestarzałej już wersji Okhttp/Okio, dodano też wsparcie dla adnotacji @MeterTag
pozwalającej na dokonfigurowanie Micrometer.
Quarkus 3.7 to ostatnie wydanie przed Quarkus 3.8, który będzie wersją LTS. To więc też ostatnia szansa, żeby społeczność mogła całość gruntownie przetestować, do czego zachęcam.
langchain4j 0.26
Najnowsze wydanie langchain4j
, wersja 0.26, wprowadza szereg nowych funkcji podstawowych oraz integracji, mających na celu wzmocnienie możliwości frameworka w przetwarzaniu i analizie danych językowych. Wśród godnych uwagi nowych funkcji podstawowych znajduje się implementacja zaawansowanego modelu Augmented Generation (RAG) – czyli możliwość tworzenia nowych odpowiedzi na bazie zadanego tekstu źródłowego, czy też wsparcie dla multimodalnych danych wejściowych – czyli łączących tekst i grafikę, już w tej chwili pozwala na to ChatGPT, aby rozwiązywać choćby zadania z matematyki.
Chyba nigdzie GPT nie jest tak nadużywane jak w edukacji
Pod względem integracji, to wydanie poszerza kompatybilność frameworka z różnymi dostawcami modeli, takimi jak Mistral AI, Wenxin Qianfan i Cohere Rerank, oraz tak zwanych „magazynów embeddingów”, takich jak Azure AI Search, Qdrant i Vearch. Ładowarki dokumentów obejmują teraz wsparcie dla Azure Blob Storage, GitHub i Tencent COS. Ponadto, wśród znaczących aktualizacji znajduje się wsparcie dla danych wejściowych obrazów i skróconych embeddingów w OpenAI, generowanie obrazów w Vertex AI oraz wsparcie dla danych wejściowych obrazów w Ollama i Qwen.
Javalin 6.0
Javalin 6 to najnowsza wersja popularnego frameworka webowego dla Javy i Kotlin, kładącego nacisk na prostotę oraz interoperacyjność między tymi językami. Jest to de facto nakładka na serwer Jetty, skupiająca się przede wszystkim na warstwie webowej. Javalin wyróżnia się swoimi małymi rozmiarami i łatwym zrozumieniem całości – jego kod źródłowy to tylko około 8000 linii kodu Java/Kotlin oraz dodatkowo około 12000 linii testów.
Zawsze szanuje narzędzia, których wewnętrzne działanie da się zrozumieć podczas dłuższego śniadania.
Javalin 6 wprowadza wiele nowości, w tym kompletne przepisanie systemu pluginów czy przemodelowanie konfiguracji Jetty’ego. Wyłączono też domyślne użycie Wirtualnych Wątków, w nowej wersji niezbędne jest użycie flagi config.useVirtualThreads = true
i kompatybilnej wersji JDK. Usunięto też interfejs AccessManager
i zmieniono podejście do zarządzania uprawnieniami, co stanowi główną część opisaną przez towarzyszący wydaniu migration guide.
WildFly 31
WildFly 31 obejmują aktualizację MicroProfile do wersji 6.1, Hibernate do wersji 6.4 oraz wprowadzenie wsparcia (w wersji Preview) dla Jakarta MVC 2.1 poprzez projekt Eclipse Krazo. Ponadto, Reactive Messaging umożliwia teraz komunikacje przez AMQP. Pod maską, WildFly doczekał się też zmian w modularyzacji, umożliwiającej łatwiejszy rozwój rozszerzeń oraz transparentne definiowanie stabilności poszczególnych fragmentów.
Poza aktualizacjami samego serwera, WildFly ogłosił również dostępność bety WildFly Glow, zestawu narzędzi mających na celu uproszczenie i optymalizację instalacji WildFly w różnych środowiskach, głównie chmurowych. WildFly Glow analizuje artefakty aplikacji, aby zarekomendować niezbędne pakiety funkcjonalności i warstw Galleon (wsparcie Wildfly dla obrazów Dockerowych), ułatwiając sprawną i efektywną konfigurację serwera.