Kiedy zaczynałem tworzyć obecną edycję myślałem, że totalnie nie będzie o czym pisać. Okazało się jednak, że temat Observability w JVM-ie jest naprawdę ciekawy, a ostatnie ogłoszenia pozwoliły mi nieco lepiej się mu przyglądnąć. Mam nadzieje, że Wam również spodoba się taka nieco tematyczna edycja
1. Nowy JEP wprowadza stabilizacji API służącego do profilowania JVM
Sprawny profiling aplikacji to trudne wyzwanie nawet z perspektywy użytkownika, a wyobraźcie sobie, ile wyzwań niesie za sobą tworzenie takich narzędzi. Źle zaimplementowany profiling może wprowadzić duży narzut wydajnościowy na aplikacje, a w szczególnych sytuacjach po prostu ją „wysypać”.
Do tej pory popularne były dwa równoległe podejścia. Jedne z nich to używanie Agentów, czyli podprogramów uruchamianych jako proces w maszynie wirtualnej. Alternatywą było zaś użycie wewnętrznego wywołania API AsyncGetCallTrace
. API to umożliwia uniknięcie problemu zbytniego bazowania na zakłamujących wyniki SafePointach – miejscach w JVMie, w których stan aplikacji jest jasno zdefiniowany, ponieważ aktualne zostały wszystkie wątki. Może prowadzić to do znacznego biasu i zakłamania wyników pomiarów. AsyncGetCallTrace
daje dostęp do danych wewnętrznych, przez to ten problem nie występuje – daje ono bowiem mapowanie pomiędzy instrukcją/ramką/wskaźnikiem stosu a konkretnym fragmentem StackTrace. Jeśli chcecie dowiedzieć się więcej szczegółów, zapraszam do tekstu Why (Most) Sampling Java Profilers Are Fucking Terrible autorstwa Nissana Wakarta,
Z AsyncGetCallTrace
jest jednak jeden problem – nie jest ono bowiem oficjalną część standardu JDK. Spora część implementacji JDK go posiada, ale zależy to raczej od dobrej woli implementujących. Co równie ważne: jako, że nie jest oficjalnie zdefiniowane, jego rozwijanie jest trudne bez psucia ekosystemu narzędzi. Dlatego też twórcy Javy postanowili iść za ciosem i wpisać go w standard języka. Dodatkowo, skoro już i tak w tym grzebiemy, postanowiono również uzupełnić przekazywane przez metodę informacje, takie jak np. poziom kompilacji danego fragmentu kodu, jak np. czy kod był skompilowany za pomocą C1/C2 czy też np. był inlinowany. W ten sposób powstał JEP 435: Asynchronous Stack Trace VM API, mający na celu zaproponowanie AsyncGetStackTrace API
. Ma ono być wpisane w standard Javy, tak samo wydajne jak wcześniejsze rozwiązanie, a równocześnie uzupełnione o wspomniane wyżej detale.
A, i żeby wszyscy dobrze zrozumieli – wspomniane API to część HotSpot VM – a więc używa się go z poziomu C. W związku z tym w JEP-ie znajdziecie takie brzydkie słowa jak wskaźniki czy pliki nagłówkowe.
Dobra, to jeszcze a po co to komu, a komu to potrzebne? Tutaj wykorzystam okazję, żeby podrzucić Wam narzędzie, którym jest async-profiler. Ten bowiem jest jednym z najpopularniejszych konsumentów wspomnianego AsyncGetCallTrace API
, dzięki czemu stał się jednym z kluczowych narzędzi jeśli chodzi o profilowanie aplikacji na JVM. To właśnie pod kątem tego typu rozwiązań stworzony został opisywany tu JEP i pozwolić ma na stworzenie odpowiedniej wydajnej abstrakcji na ich potrzeby.
Jeśli szukacie szybkiego wprowadzenia do tematu, post Krzysztofa Ślusarskiego z Hazelcast jest w sam raz dla Was. Nieco więcej detali znajdziecie w A Guide to async-profiler opublikowanym na Baeldung. Jeśli zaś będziecie chcieli podjeść do tematu profilingu na poważnie, polecam trzy godzinny kurs wideo prezentujący narzędzie.
I ja wiem, masa czasu, ale dla „produktywnych i szanujących czas”:
Źródła
- Why (Most) Sampling Java Profilers Are Fucking Terrible
- JVM Anatomy Quark #22: Safepoint Polls
- A Guide to async-profiler
- Continuous profiling with async-profiler
- Async-profiler with Andrei Pangin. Webinar by Luxoft
Zainstaluj teraz i czytaj tylko dobre teksty!
2. Dlaczego Quarkus wycofuje się ze standardów MicroProfile dotyczących observability?
Było już o profilowaniu, kontynuując więc temat „obserwowalności”, przyglądniemy się tematowi JVM-owych metryk. Okazje ku temu daje nam ogłoszenie ze strony Quarkusa – framework bowiem postanowił podzielić się ze społecznością swoimi planami, jeśli chodzi o wsparcie najbardziej znanych narzędzi do telemetrii. Kilka decyzji jest zaś interesujące dla każdego śledzącego ekosystem bibliotek i standardów, nawet jeśli nie używają samego Quarkusa.
Zacznijmy trochę od nakreślenia horyzontu organizacyjno-społecznościowego. Jeśli chodzi o Tracing – czyli śledzenia poszczególnych zdarzeń w ramach aplikacji – organizacją zajmującą się tworzeniem standardów jest Cloud Native Computing Foundation (w skrócie CNCF). Przez lata rozwijane było kilka konkurencyjnych projektów, takich jak OpenCensus czy OpenTracing. Ten ostatni trafił do MicroProfile jako MicroProfile OpenTracing API, referencyjnej implementacji tegoż – SmallRye OpenTracing – używa Quarkus.
CNCF początkiem roku zdecydował się na porzucenie rozwoju OpenTracingu na rzecz OpenTelemetry, będącego nieco szerszym projektem, przez co MicroProfile OpenTracing API oberwało rykoszetem i również przestanie być wspierane. Na jego miejsce powstało MicroProfile Telemetry Tracing, implementujące standard Tracingu pochodzący OpenTelemetry. Trafi ono do nadchodzącego MicroProfile 6.0 i to właśnie ono będzie w przyszłości używane przez Quarkusa. Oznacza to, że wszystkich użytkowników MP OpenTracing czeka migracja, oba standardy nie są bowiem ze sobą w pełni kompatybilne.
To jednak nie koniec jeśli chodzi o poszerzenie zakresu współpracy między Quarkusem, a OpenTelemetry. Okazuje się bowiem, że framework postanowił porzucić wsparcie dla MicroProfile Metrics API, standardu metryk rozwijanego w ramach sam MicroProfile. Zamiast tego przyszłe wersje Quarkusa używać będą Micrometer, podobnej w swojej naturze do SLF4J fasady umożliwiającej pracę z wieloma systemami metryk. Kluczowym dla podjęcia takiej decyzji jest rychła stabilizacja OpenTelemetry Metrics – czyli komplementarnego dla OpenTelemetry Tracing standardu metryk – który przez Micrometer jest wspierany. W związku z tym przerwane zostaną prace nad rozwojem quarkusowym rozszerzeniem dla SmallRye Metrics, referencyjnej implementacji standardu pochodzącego z MicroProfile.
Całość sytuacji każe nam przemyśleć, jak rozumiemy standardy w dzisiejszym ekosystemie programistycznym. Stajemy bowiem przed interesującym problemem – co jeśli standard Javowy (a za taki już chyba można uznać MicroProfile) nie implementuje ogólnego standardu rynkowego, takiego jak OpenTelemetry Metrics? Jak w takiej sytuacji powinny zachować się frameworki? Ja z mojej perspektywy popieram decyzje tego Quarkusa – OpenTelemetry w tej chwili ma wsparcie w większej ilości ekosystemów, przez co zarówno dostawcy chmurowi, jak i twórcy narzędzi mają większą motywację do wspierania go out-of-the-box. W praktyce oznacza to więc mniejsze obciążenie programistów powtarzalnym, infrastrukturalnym plumbingiem. Z drugiej jednak strony, trochę staje to w kontrze do obietnic takich projektów jak MicroProfile z ich wspólnym API standardem implementowanym w różny sposób przez poszczególnych vendorów.
Tak naprawdę najlepszym rozwiązaniem byłoby, że jeśli już powiedziało się A, tworząc MP Telemetry Tracing, to powinno powstać MP Telemetry Metrics. Rozumiem jednak, że zbytnie rozdmuchanie ilość konkurencyjnych API w pojedynczym standardzie też nikomu nie służy. Udowadnia to, że standaryzacja jest żmudnym i wyboistym procesem.