Lab · Studium przypadku
Poprawna migracja, która nie przeszła własnego progu
W skrócie: W prywatnym eksperymencie zmiana układu danych dała znakomity wynik na uproszczonym kernelu, ale nie przyniosła wymaganej poprawy na reprezentatywnym obciążeniu obliczeniowym. Kryteria opłacalności zapisano przed pomiarem i nie dostosowano ich później do wyniku. Przypadek pokazuje, dlaczego poprawność techniczna i udany pilot nie wystarczają do uzasadnienia zmiany architektury.
01 / Sześćdziesiąt pięć procent w pilocie
Zmiana układu danych w eksperymentalnym silniku JVM przyniosła w pilotażowym benchmarku 65,5% większą przepustowość.
To rezultat, przy którym łatwo zacząć planować migrację całego systemu.
Zamiast przechowywać oddzielny obiekt dla każdego punktu danych, nowy wariant organizował wartości w osobnych tablicach. Taka reprezentacja może ograniczać narzut obiektów i poprawiać wykorzystanie pamięci podręcznej procesora.
Wynik wyglądał obiecująco. Miał jednak istotne ograniczenie: pilot sprawdzał uproszczony fragment obliczeń, bez zależności od stanu utrzymywanego pomiędzy kolejnymi operacjami.
Kiedy wariant kolumnowy przetestowano na reprezentatywnym obciążeniu ze stanem, poprawa przepustowości wyniosła 1,80%.
Nowa implementacja została przetestowana, a zachowane dokumenty raportowały zgodność wyników obu wariantów. Nie uzasadniało to jednak zastąpienia istniejącego rozwiązania.
Żeby zrozumieć dlaczego, trzeba wrócić do problemu, który doprowadził do tego eksperymentu.
02 / Problem nie zaczynał się od układu danych
Prace nad wydajnością były częścią rozwoju prywatnego, eksperymentalnego silnika obliczeniowego JVM.
Silnik przetwarzał uporządkowane sekwencje danych, wykonując powtarzalne obliczenia, których rezultat mógł zależeć od stanu wypracowanego w poprzednich krokach. Istotne były zarówno przepustowość, jak i koszt alokacji pamięci.
W takim systemie wydajność ma znaczenie. Każda kolejna konfiguracja obliczeń, wariant badanej hipotezy czy ponowny przebieg zwiększa ilość pracy do wykonania.
Nie oznacza to jednak, że każdy element powinien być optymalizowany za wszelką cenę.
Istniejąca implementacja była już zoptymalizowana. Kolejne zmiany należało więc oceniać względem rzeczywistego punktu odniesienia, a nie teoretycznej korzyści wynikającej z zastosowania określonej technologii.
Rozważałem kilka kierunków dalszego rozwoju: ograniczenie alokacji obiektów, zmianę reprezentacji danych, wykorzystanie operacji wektorowych i przeniesienie wybranych struktur poza stertę maszyny wirtualnej.
Każda z tych technik mogła być użyteczna. Żadna sama w sobie nie rozwiązywała jeszcze problemu.
Co więcej, system obejmował obciążenia o różnych charakterystykach. Przetwarzanie dużych zbiorów danych, wielokrotne wykonywanie pełnych przebiegów obliczeniowych i operacje wymagające krótkiego czasu reakcji nie mają identycznych wymagań. Optymalizacja jednego rodzaju pracy nie musi poprawiać pozostałych.
Po przeanalizowaniu możliwych kierunków zdecydowałem o wydzieleniu osobnego toru prac inżynierskich.
Nie był to projekt przepisania silnika na nową architekturę. Pierwszym zadaniem było określenie kontraktu reprezentacji danych, granic optymalizacji i sposobu sprawdzenia, czy dalsze zmiany w ogóle są uzasadnione.
Równolegle rozwijano inne części systemu, dlatego istotne było również udostępnienie tych ustaleń pozostałym pracom, bez narzucania im przedwcześnie nowej implementacji.
Zgoda na zbadanie kierunku technicznego nie oznacza jeszcze decyzji o jego wdrożeniu.
03 / Hipoteza i cel eksperymentu
Jednym z rozważanych kierunków była zmiana reprezentacji danych z układu obiektowego na kolumnowy.
Rozważany mechanizm opierał się na prostym założeniu: przechowywanie wartości w ciągłych tablicach może zmniejszyć koszt dostępu do danych, ograniczyć alokacje i poprawić wykorzystanie procesora.
Pozostawało jednak pytanie o znaczenie tej zmiany dla całego silnika.
W izolowanej pętli obliczeniowej dostęp do danych może odpowiadać za istotną część kosztu. W szerszym procesie dochodzą obliczenia pośrednie, aktualizacja stanu algorytmu i inne operacje, których sama zmiana reprezentacji nie przyspiesza.
Dlatego cel eksperymentu nie sprowadzał się do wykazania, że nowy układ danych potrafi być szybszy.
Należało ustalić, czy jego zastosowanie w istniejącym silniku przyniesie wystarczającą korzyść bez zmiany semantyki obliczeń i wyników.
To wymagało osobnego sprawdzenia poprawności oraz wydajności. Pozytywny wynik jednego z tych sprawdzeń nie mógł zastąpić drugiego.
04 / Próg zapisany przed wynikiem
Przed pomiarem opłacalności migracji w repozytorium zapisano dwa liczbowe kryteria:
- poprawa przepustowości o co najmniej 15%;
- redukcja alokacji pamięci o co najmniej 50%.
W historycznym kontrakcie wartości te oznaczono jako proposed, czyli proponowane. Zachowany dokument nie stanowi samodzielnego dowodu ich formalnego zatwierdzenia przez właściciela.
Można natomiast ustalić ich chronologię.
Kryteria znalazły się w wersjonowanym kontrakcie przed pomiarem rozstrzygającym. Odstęp wynosił niespełna dwie godziny.
Podczas późniejszej rekonstrukcji sprawdzono również, czy progi nie zostały zmienione po poznaniu wyniku. Ich zapis pozostał identyczny bajtowo przez kolejne miesiące.
To ważne, ponieważ migracja przygotowana kosztem pracy inżynierskiej tworzy naturalną pokusę, żeby po niekorzystnym pomiarze znaleźć nowe uzasadnienie dla jej wdrożenia.
Można obniżyć próg. Można wybrać korzystniejszy benchmark. Można też uznać, że skoro implementacja jest poprawna i częściowo gotowa, szkoda jej nie wykorzystać.
W tym przypadku wynik można było porównać z kryteriami zapisanymi przed pomiarem.
Historyczne sformułowanie warunku nie było w pełni jednoznaczne co do relacji logicznej między obiema wartościami. Nie wpływa to jednak na ocenę przypadku: testowany wariant nie osiągnął żadnego z progów.
05 / Dwa pomiary, dwie odpowiedzi
Najpierw sprawdzono zmianę na uproszczonym kernelu bez stanu.
Wynik był wyraźnie pozytywny:
| Pomiar | Stary układ | Nowy układ | Zmiana |
|---|---|---|---|
| Pilot bez stanu — operacje/s | 5 132,9 | 8 493,6 | +65,5% |
| Przetwarzanie ze stanem — operacje/s | 11,0704 | 11,2696 | +1,80% |
To dwa różne obciążenia, z odrębnymi punktami odniesienia. Ich bezpośrednie zestawienie nie oznacza, że przepustowość tego samego programu spadła z 65,5% do 1,8%.
Pokazuje natomiast, że efekt optymalizacji silnie zależał od tego, co rzeczywiście wykonywał program.
Dokument pilota sam zastrzegał, że pomiar na kernelu bez stanu nie rozstrzyga opłacalności migracji pełnej ścieżki obliczeniowej.
Drugi benchmark obejmował ścieżkę przetwarzania, w której kolejne operacje zależały od utrzymywanego stanu, a dostęp do danych stanowił tylko część całkowitego kosztu obliczeń. Oba warianty wykonywały tę samą logikę na tych samych danych wejściowych, przy zmianie sposobu ich udostępniania. Był to pomiar bliższy docelowemu zastosowaniu niż uproszczony pilot, choć nie obejmował wszystkich możliwych obciążeń systemu.
Dla tego obciążenia zachował się również surowy zapis alokacji:
| Parametr | Wynik nowego układu | Zapisany próg |
|---|---|---|
| Przepustowość | +1,80% | co najmniej +15% |
| Alokacja na operację | −0,42% | redukcja co najmniej 50% |
Alokacja oznacza liczbę bajtów przydzielonych w trakcie jednej operacji, nie rozmiar pamięci zajmowanej przez proces.
Pomiar przeprowadzono na jednej maszynie, z jednym uruchomieniem maszyny wirtualnej na wariant, pięcioma iteracjami rozgrzewki i ośmioma pomiarowymi.
Przedziały błędu przepustowości nakładały się, więc sam wynik +1,80% nie stanowi mocnego dowodu trwałej poprawy.
Nie trzeba jednak rozstrzygać dokładnej wielkości tego niewielkiego przyrostu, aby zauważyć, że nie wykazano korzyści wymaganej do uzasadnienia migracji.
A co z poprawnością?
Zmiana reprezentacji danych nie miała zmieniać logiki przetwarzania ani rezultatów obliczeń.
Zachowane dokumenty raportują pozytywne wyniki nazwanych testów równoważności dla obu wariantów. Obejmowały one zgodność sekwencji rozstrzygnięć algorytmu oraz identyczność końcowego zapisu wyników.
Nie zachował się jednak w zweryfikowanym zakresie surowy wydruk wykonania tych testów. Można więc mówić o raportowanej zgodności funkcjonalnej, ale nie o jej niezależnym ponownym potwierdzeniu podczas przygotowania artykułu.
Nawet przy przyjęciu zgodności obu implementacji pozostaje drugie pytanie: co system zyskuje dzięki migracji?
Na badanym obciążeniu odpowiedź była niewystarczająca.
06 / Dlaczego dobry pilot nie wystarczył
Wynik +65,5% nie był błędem tylko dlatego, że późniejszy pomiar wykazał +1,80%.
Pilot odpowiadał na inne pytanie.
Pokazał, że w określonym fragmencie obliczeń nowa reprezentacja danych może działać znacznie szybciej.
Nie dowodził jednak, że koszt tego fragmentu dominuje w pełnej ścieżce przetwarzania.
To zasadnicza różnica między pomiarem potencjału techniki a pomiarem wartości jej zastosowania.
Jeżeli optymalizowany fragment odpowiada jedynie za część całkowitego kosztu, nawet duża poprawa jego wydajności może przełożyć się na niewielki zysk całego procesu.
Nie oznacza to automatycznie, że znamy dokładną przyczynę różnicy między wynikami. Jej wyjaśnienie wymagałoby osobnego rozdzielenia kosztów poszczególnych operacji w reprezentatywnym obciążeniu.
Eksperyment nie musiał jednak rozstrzygać każdej z tych przyczyn, żeby odpowiedzieć na pytanie o migrację.
Pilot wykazał potencjał techniki. Właściwy pomiar nie wykazał wystarczającej wartości jej zastosowania.
07 / Nie każda wykonana zmiana powinna zostać przyjęta
Po właściwym pomiarze w dokumentacji zapisano negatywną rekomendację: kryteria opłacalności nie zostały osiągnięte, więc migracji nie należy wykonywać.
Wariant kolumnowy przetestowano na reprezentatywnym obciążeniu ze stanem, lecz nie przyjęto go jako zastępstwa dotychczasowej implementacji.
Dalsze prace wydajnościowe prowadzono w oparciu o istniejącą reprezentację danych. Był to osobny zakres optymalizacji, którego późniejszych wyników nie należy zaliczać na poczet odrzuconej migracji.
Dokumentacja pozwala ustalić wynik eksperymentu, treść rekomendacji i faktyczny dalszy stan projektu. Nie zachował się w zweryfikowanym zakresie osobny zapis mojego końcowego zatwierdzenia rekomendacji.
To rozróżnienie nie zmienia technicznego rezultatu.
Nieprzyjęcie rozwiązania nie unieważniło pracy wykonanej nad jego sprawdzeniem. Dostarczyło informacji o granicach przydatności badanego mechanizmu w określonych warunkach.
Najważniejszy rezultat jest prosty: nowy wariant nie zastąpił istniejącego rozwiązania wyłącznie na podstawie raportowanej poprawności działania i efektownego wyniku pilota.
Prace nad układem kolumnowym wykazały jego możliwości w ograniczonym zakresie. Nie dostarczyły wystarczającego argumentu za zmianą istniejącego silnika.
To również jest użyteczny rezultat pracy inżynierskiej.
08 / Co rzeczywiście pokazał eksperyment
Na początku nie było pewności, czy zmiana reprezentacji danych uzasadni koszt i ryzyko przebudowy.
Dlatego rozdzielono prace nad kontraktem, eksperyment na ograniczonym fragmencie oraz pomiar na reprezentatywnym obciążeniu.
Pozytywny wynik pilota nie zakończył procesu weryfikacji.
Właściwy benchmark pozwolił skonfrontować obiecujący wariant z warunkami, które miały uzasadniać jego zastosowanie.
Eksperyment odpowiedział na trzy różne pytania:
- Czy rozwiązanie ma potencjał techniczny? Tak, w zbadanym pilocie.
- Czy zachowuje funkcjonalną równoważność? Tak raportują dokumenty testowe, z ograniczeniami dostępnego materiału.
- Czy wykazano wystarczającą poprawę dla docelowej migracji? Nie, w badanym obciążeniu.
Nie wykazano tym samym, że reprezentacja kolumnowa jest rozwiązaniem złym albo że nie przyniosłaby korzyści w innym zastosowaniu.
Wykazano coś węższego, ale wystarczającego dla rozpatrywanej zmiany: na tej trasie obliczeniowej, względem istniejącej implementacji, nie osiągnęła zapisanego progu opłacalności.
To jest moment, w którym wynik techniczny spotyka się z decyzją architektoniczną.
Nie wystarczy wiedzieć, że coś da się zrobić szybciej. Trzeba jeszcze wiedzieć, czy przyspieszamy właściwą część systemu, jakie korzyści z tego wynikają i czy uzasadniają one wprowadzenie dodatkowej złożoności.
Poprawnie wykonana zmiana może być jednocześnie zmianą, której nie warto przyjmować.
09 / Ograniczenia
To prywatny eksperyment badawczy, bez użytkowników i bez produkcyjnego wdrożenia opisywanej migracji.
Wyniki pochodzą z jednego środowiska i ograniczonej liczby przebiegów. Nie uzasadniają ogólnych twierdzeń o przewadze jednego sposobu reprezentacji danych nad drugim.
Pomiar przepustowości na pełnej ścieżce obliczeniowej miał nakładające się przedziały błędu. Dokumenty raportujące zgodność funkcjonalną wskazują konkretne testy, ale podczas rekonstrukcji nie odtworzono ich wykonania z surowych zapisów.
Kryteria zapisano przed pomiarem, lecz miały status propozycji. Historia repozytorium pozwala sprawdzić ich wcześniejsze istnienie i późniejszą niezmienność, ale nie stanowi kompletnego rejestru autoryzacji.
Zachowane konsultacje dokumentują kontekst problemu i część decyzji dotyczących organizacji prac. Nie obejmują całej historii realizacji ani wszystkich późniejszych rozstrzygnięć.
Źródła techniczne pozostają prywatne, dlatego publikacja nie umożliwia pełnej, niezależnej reprodukcji historycznego eksperymentu.
10 / Pochodzenie materiału
Kontekst przedsięwzięcia i decyzja o wydzieleniu prac inżynierskich mają oparcie w zachowanych rozmowach z okresu prowadzenia projektu. Techniczny przebieg eksperymentu odtworzono z dokumentacji, historii zmian i zapisanych wyników pomiarów.
Osobiście kierowałem pracami i aktywnie nadzorowałem cały proces, od początku do końca. Nie wszystkie działania nadzorcze i decyzje były odnotowywane w repozytorium jako odrębne zatwierdzenia.
Przy realizacji zadań projektowych, implementacyjnych, pomiarowych i dokumentacyjnych korzystałem z agentów AI.
Przy przygotowaniu artykułu przeanalizowano zachowane materiały i wyniki. Nie uruchamiano ponownie badanego kodu ani benchmarków. Niepubliczne pozostają szczegóły implementacji, pełne zapisy konsultacji, dane badawcze oraz wewnętrzne materiały dowodowe.
Za wybór tematu, zakres ujawnienia i publikowaną interpretację odpowiadam jako autor.
11 / Od autora
Najciekawszy jest tutaj dla mnie wynik, który nie pozwolił przyjąć technicznie obiecującego rozwiązania.
Pilot pokazał istotną poprawę. Pełniejszy pomiar nie potwierdził jej w wymaganym zakresie.
Nie było potrzeby zmieniać kryterium ani szukać zastępczego uzasadnienia migracji.
Dobry eksperyment nie musi potwierdzać sensowności zmiany. Może również dostarczyć wystarczających powodów, żeby jej nie wykonywać.
Jak cytować
Bartłomiej Pietrzyk, „Poprawna migracja, która nie przeszła własnego progu”
4digital Lab, 27.10.2026, https://lab.4digital.cloud/pl/poprawna-migracja-ktora-nie-przeszla-wlasnego-progu/
Warunki wykorzystania opracowań i danych ustalane są indywidualnie.