Optymalizacja flag JVM Javy dla serwerów Minecraft: pełny poradnik

Optymalizacja flag JVM Javy dla serwerów Minecraft: pełny poradnik

Każdy serwer Minecraft działa na Java Virtual Machine, a domyślne ustawienia JVM nie są projektowane pod serwery gamingowe. Są dostosowane do uniwersalnych aplikacji, gdzie przepustowość ważniejsza od opóźnienia. Dla serwera Minecraft opóźnienie decyduje o wszystkim. Pauza garbage collectora 200ms oznacza widoczny lag-spike, który gracze czują natychmiast. W MineGuard konfigurowaliśmy JVM dla setek serwerów i w tym poradniku dzielimy się wszystkim, co wiemy.

Co tak naprawdę robią flagi JVM

Gdy uruchamiasz serwer komendą java -jar server.jar, JVM używa domyślnych ustawień do zarządzania pamięcią, garbage collection i optymalizacji w czasie wykonywania. Te ustawienia są dostosowane pod uniwersalne obciążenia. Minecraft nie jest uniwersalny. Tworzy i wyrzuca miliony małych obiektów co sekundę (aktualizacje bloków, ticki encji, bufory pakietów) i potrzebuje stabilnego taimingu ticków bez pauz dłuższych niż 50ms.

Flagi JVM pozwalają nadpisać te ustawienia. Kontrolują objętość pamięci JVM, jaki garbage collector pracuje, jak agresywnie zbiera i dziesiątki innych parametrów. Poprawna kombinacja może skrócić pauzy GC o 80% i ustabilizować TPS na pełnych 20.

Podstawy pamięci: -Xmx i -Xms

Dwie najważniejsze flagi to -Xmx (maksymalny rozmiar heap) i -Xms (początkowy rozmiar heap). Zawsze ustawiaj je na tę samą wartość:

-Xms8G -Xmx8G

Dlaczego te same? Gdy -Xms jest mniejsze niż -Xmx, JVM startuje z mniejszą objętością pamięci i dynamicznie powiększa heap. Przy każdym powiększeniu JVM zatrzymuje proces na czas realokacji. Ustawienie tych samych wartości całkowicie eliminuje te pauzy. JVM alokuje całą pamięć na starcie i już więcej nie zmienia rozmiaru.

Ile RAM potrzebuje twój serwer?

Praktyczne rekomendacje według liczby graczy i złożoności świata:

  • 1-20 graczy: 2-4 GB
  • 20-50 graczy: 4-6 GB
  • 50-100 graczy: 6-8 GB
  • 100-200 graczy: 8-12 GB
  • 200+ graczy: 12-16 GB

Te liczby zakładają Paper albo Purpur z umiarkowaną liczbą pluginów (15-30). Mocno zmodyfikowane serwery (Forge/Fabric z 100+ modami) mogą wymagać 2-4 GB więcej.

Typowy błąd: przydzielanie za dużo RAM. Jeśli masz dostępne 32 GB, nie stawiaj -Xmx32G. Garbage collector musi przeskanować cały heap przy zbieraniu. Większy heap = dłuższe pauzy GC. Daj serwerowi tyle, ile potrzebuje, plus 20-30% zapasu, nie więcej.

Garbage collection: serce konfiguracji JVM

Garbage collection (GC) to proces znajdowania i zwalniania pamięci, której twój serwer już nie używa. JVM robi to automatycznie, ale sposób, w jaki to się dzieje, ma ogromne znaczenie. Podczas pauzy GC twój serwer dosłownie przestaje przetwarzać ticki.

G1GC (Garbage First Garbage Collector)

G1GC to rekomendowany garbage collector dla serwerów Minecraft i podstawa flag Aikara. Dzieli heap na regiony i zbiera te, w których jest najwięcej śmieci (stąd nazwa). Takie podejście daje przewidywalny czas pauz.

Dlaczego G1GC dobrze pasuje do Minecrafta:

  • Docelowy maksymalny czas pauzy (konfigurowany przez MaxGCPauseMillis)
  • Efektywnie pracuje z heapami od 2 do 16 GB
  • Wykonuje podstawową pracę concurrent, bez zatrzymywania serwera
  • Świetnie radzi sobie z obciążeniami generującymi dużo krótkożyjących obiektów (a Minecraft robi to stale)

ZGC (Z Garbage Collector)

ZGC to collector z niskim opóźnieniem dopasowany do submilisekundowych pauz. Brzmi idealnie? Niezupełnie. ZGC poświęca przepustowość na rzecz czasu pauz. Używa więcej CPU do osiągnięcia tak małych pauz, a na serwerach z ograniczoną liczbą rdzeni ten narzut może zaszkodzić TPS.

ZGC warto spróbować, jeśli:

  • Masz 8+ rdzeni CPU dedykowanych dla serwera
  • Heap 16 GB albo większy
  • Używasz Java 21+ (ZGC znacznie się poprawił w ostatnich wersjach)

Dla większości serwerów G1GC z ustawieniami Aikara zadziała lepiej niż ZGC.

Shenandoah

Shenandoah to kolejny collector z niskimi pauzami, podobny w celach do ZGC, ale z innym podejściem. Dostępny w buildach OpenJDK (nie Oracle JDK). Podobnie jak ZGC, wymienia CPU na czas pauz i najlepiej pracuje na serwerach z dostateczną liczbą rdzeni.

Nasza rekomendacja: zacznij od G1GC. Przełączaj się na ZGC albo Shenandoah tylko, jeśli profilowałeś serwer przez Spark i potwierdziłeś, że pauzy GC to twoje wąskie gardło, a masz zapas CPU.

Flagi Aikara: złoty standard

Flagi Aikara to zestaw flag JVM specjalnie dostosowanych do serwerów Minecraft. Sprawdzone na serwerach z tysiącami graczy i dopracowywane latami. Rozbierzmy, co robi każda flaga:

Rozbiór głównych flag

-XX:+UseG1GC

Włącza garbage collector G1 zamiast domyślnego.

-XX:+ParallelRefProcEnabled

Przetwarza obiekty referencyjne (WeakReferences, SoftReferences) równolegle, nie sekwencyjnie. Pluginy Minecrafta tworzą dużo takich obiektów.

-XX:MaxGCPauseMillis=200

Wskazuje G1GC docelową maksymalną pauzę 200ms. Collector dostosowuje swoje zachowanie, żeby zostać w ramach tego celu.

-XX:+UnlockExperimentalVMOptions

Włącza eksperymentalne flagi niedostępne domyślnie. Potrzebne do niektórych parametrów poniżej.

-XX:+DisableExplicitGC

Zakazuje pluginom wywoływać System.gc() ręcznie. Niektóre źle napisane pluginy robią to, wywołując niepotrzebne pełne pauzy GC.

-XX:G1NewSizePercent=30
-XX:G1MaxNewSizePercent=40

Przydziela 30-40% heapu pod młodą generację (gdzie trafiają nowe obiekty). Minecraft tworzy tony krótkożyjących obiektów, więc większa młoda generacja oznacza rzadsze zbieranie.

-XX:G1HeapRegionSize=8M

Ustawia rozmiar każdego regionu G1 na 8 MB. Większe regiony zmniejszają narzut dla dużych heapów, ale mogą zwiększać pauzy dla małych. 8M to optymalny balans dla serwerów z 4-16 GB.

-XX:G1ReservePercent=20

Rezerwuje 20% heapu jako bufor bezpieczeństwa. To zapobiega tym strasznym pełnym pauzom GC 'to-space exhausted', które zdarzają się, gdy collectorowi kończą się wolne regiony.

-XX:G1MixedGCLiveThresholdPercent=90

Zbiera region tylko, jeśli 90% lub więcej jego zawartości to śmieci. To zmniejsza objętość żywych danych, które trzeba kopiować przy zbieraniu.

-XX:InitiatingHeapOccupancyPercent=15

Uruchamia cykl GC concurrent, gdy zajęte jest 15% heapu. To agresywne (domyślnie 45%), ale oznacza, że collector zaczyna pracę wcześnie i ma więcej czasu zakończyć bez pauzy.

-XX:SurvivorRatio=32

Zmniejsza rozmiar obszaru survivor. W obciążeniach Minecrafta obiekty albo umierają natychmiast, albo żyją długo (jak załadowane chunki). Mniej potrzeby trzymania obiektów między zbieraniem.

-XX:+PerfDisableSharedMem

Wyłącza zapis statystyk GC do pliku pamięci współdzielonej. Eliminuje okresowe spike'i opóźnienia od operacji plikowych.

-XX:MaxTenuringThreshold=1

Promuje obiekty do starej generacji po zaledwie 1 cyklu GC. W połączeniu z dużą młodą generacją dobrze pracuje dla wzorca alokacji Minecrafta.

GraalVM: alternatywne środowisko uruchomieniowe

GraalVM to alternatywna dystrybucja JDK z zaawansowanym kompilatorem JIT. Dla serwerów Minecraft GraalVM może dać 5-15% lepszą wydajność w porównaniu do zwykłego OpenJDK, zwłaszcza w scenariuszach obliczeniowo ciężkich, takich jak generacja świata i przetwarzanie redstonu.

Zalety GraalVM:

  • Bardziej agresywna optymalizacja JIT
  • Lepszy inlining wywołań metod
  • Ulepszona analiza ucieczki (zmniejsza alokacje w heapie)
  • Działa jako zamiennik OpenJDK bez zmian

Żeby używać GraalVM, pobierz go z oficjalnej strony i zamień swoją instalację Javy. Wszystkie flagi Aikara działają z GraalVM. Można też dodać specyficzne flagi:

-XX:+UseJVMCICompiler
-XX:+EagerJVMCI

Uwaga: GraalVM Community Edition jest darmowe. Enterprise Edition oferuje dodatkowe optymalizacje, ale wymaga licencji.

Duże strony pamięci

Duże strony (Large Pages, znane też jako Huge Pages) pozwalają JVM używać stron pamięci po 2 MB zamiast domyślnych 4 KB. To zmniejsza misses TLB (Translation Lookaside Buffer) i poprawia wydajność dostępu do pamięci o 5-10%.

Żeby włączyć duże strony:

  1. Skonfiguruj OS (Linux): echo "vm.nr_hugepages=4096" >> /etc/sysctl.conf && sysctl -p
  2. Dodaj flagę JVM: -XX:+UseLargePages

Liczba potrzebnych huge pages to rozmiar heapu podzielony przez 2 MB. Dla heapu 8 GB: 8192 / 2 = 4096 stron.

Duże strony wymagają konfiguracji na poziomie root i są najbardziej przydatne na dedykowanych serwerach. Jeśli jesteś na hostingu, pomiń ten krok.

Deduplikacja stringów

Stringi Javy z identyczną zawartością można deduplikować dla oszczędności pamięci. To szczególnie przydatne dla Minecrafta, bo w pamięci istnieje dużo identycznych stringów (nazwy przedmiotów, typy bloków, wiadomości czatu).

-XX:+UseStringDeduplication

Ta flaga prawie nie obciąża CPU i może zmniejszyć zużycie pamięci o 5-10%. Działa tylko z G1GC, którego używają flagi Aikara.

Gotowe zestawy flag

Oto gotowe do użycia zestawy flag dla różnych rozmiarów serwerów. Kopiuj w całości i używaj jako komendę startową.

Mały serwer (2 GB RAM, 1-20 graczy)

java -Xms2G -Xmx2G -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:+AlwaysPreTouch -XX:G1NewSizePercent=30 -XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=4M -XX:G1ReservePercent=20 -XX:G1MixedGCLiveThresholdPercent=90 -XX:InitiatingHeapOccupancyPercent=15 -XX:SurvivorRatio=32 -XX:+PerfDisableSharedMem -XX:MaxTenuringThreshold=1 -XX:+UseStringDeduplication -jar server.jar --nogui

Uwaga: G1HeapRegionSize ustawione na 4M dla serwera 2 GB (mały heap wygrywa z mniejszymi regionami).

Średni serwer (4 GB RAM, 20-50 graczy)

java -Xms4G -Xmx4G -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:+AlwaysPreTouch -XX:G1NewSizePercent=30 -XX:G1MaxNewSizePercent=40 -XX:G1HeapRegionSize=8M -XX:G1ReservePercent=20 -XX:G1MixedGCLiveThresholdPercent=90 -XX:InitiatingHeapOccupancyPercent=15 -XX:SurvivorRatio=32 -XX:+PerfDisableSharedMem -XX:MaxTenuringThreshold=1 -XX:+UseStringDeduplication -jar server.jar --nogui

Duży serwer (8 GB RAM, 50-100 graczy)

java -Xms8G -Xmx8G -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:+AlwaysPreTouch -XX:G1NewSizePercent=40 -XX:G1MaxNewSizePercent=50 -XX:G1HeapRegionSize=16M -XX:G1ReservePercent=20 -XX:G1MixedGCLiveThresholdPercent=90 -XX:InitiatingHeapOccupancyPercent=15 -XX:SurvivorRatio=32 -XX:+PerfDisableSharedMem -XX:MaxTenuringThreshold=1 -XX:+UseStringDeduplication -XX:+UseLargePages -jar server.jar --nogui

Uwaga: zwiększone G1NewSizePercent do 40 i G1MaxNewSizePercent do 50 dla większego heapu. Dodano UseLargePages (wymaga konfiguracji OS).

Serwer korporacyjny (16 GB RAM, 200+ graczy)

java -Xms16G -Xmx16G -XX:+UseG1GC -XX:+ParallelRefProcEnabled -XX:MaxGCPauseMillis=200 -XX:+UnlockExperimentalVMOptions -XX:+DisableExplicitGC -XX:+AlwaysPreTouch -XX:G1NewSizePercent=40 -XX:G1MaxNewSizePercent=50 -XX:G1HeapRegionSize=16M -XX:G1ReservePercent=20 -XX:G1MixedGCLiveThresholdPercent=90 -XX:InitiatingHeapOccupancyPercent=15 -XX:SurvivorRatio=32 -XX:+PerfDisableSharedMem -XX:MaxTenuringThreshold=1 -XX:+UseStringDeduplication -XX:+UseLargePages -jar server.jar --nogui

Dla serwerów z 16 GB można też przetestować ZGC jako alternatywę:

java -Xms16G -Xmx16G -XX:+UseZGC -XX:+AlwaysPreTouch -XX:+DisableExplicitGC -XX:+UseLargePages -jar server.jar --nogui

ZGC wymaga mniej flag konfiguracyjnych, bo dostosowuje się sam. Przetestuj obie konfiguracje i porównaj przez profiler Spark.

Typowe błędy

Błąd 1: za dużo RAM. Heap 32 GB na serwerze z 20 graczami da ci dłuższe pauzy GC, nie lepszą wydajność. Garbage collector musi przeskanować cały heap. Trzymaj rozmiar optymalny.

Błąd 2: niewłaściwy garbage collector. CMS (Concurrent Mark Sweep) był popularny latami, ale usunięto go w Javie 14. Jeśli twój skrypt startowy wciąż zawiera -XX:+UseConcMarkSweepGC, zaktualizuj go natychmiast. G1GC to właściwy wybór.

Błąd 3: różne -Xms i -Xmx. Ustawienie -Xms512M -Xmx8G oznacza, że JVM będzie dziesiątki razy zmieniać rozmiar heapu w miarę ładowania serwera, powodując przycinki i pauzy w pierwszych minutach pracy.

Błąd 4: używanie Javy 8. Java 8 jest przestarzała. Każda nowa wersja Javy przynosi ulepszenia GC, patche bezpieczeństwa i optymalizacje wydajności. Używaj minimum Javy 21 LTS. W Javie 21 G1GC i ZGC są znacznie ulepszone w porównaniu ze starymi wersjami.

Błąd 5: ignorowanie logów GC. Dodaj -Xlog:gc*:file=gc.log:time do swoich flag. To stworzy plik logu pokazujący, co dokładnie robi garbage collector. Użyj narzędzi GCViewer albo GCEasy do analizy.

Poza JVM: wydajność sieci też ma znaczenie

Możesz dostroić JVM do perfekcji, ale jeśli twój serwer jest pod atakiem DDoS albo floodem botów, to wszystko nie ma znaczenia. Wydajność serwera i wydajność sieci to dwie strony tej samej monety.

W MineGuard bierzemy na siebie stronę sieciową. Nasz filtr działa na poziomie pakietów, weryfikując połączenia i blokując szkodliwy ruch, zanim dotrze do twojego serwera. Narzut? Mniej niż 1ms dodanego opóźnienia. Twoi gracze nie zauważą naszej ochrony, ale na pewno zauważą brak lag-spike'ów od floodów botów przeciążających serwer.

Optymalizuj flagi JVM pod wewnętrzną wydajność. Zagrożenia zewnętrzne zostaw nam. Razem to serwer, który trzyma stabilne 20 TPS w każdych warunkach.


Chroń swój serwer przed atakami DDoS

Darmowa ochrona z konfiguracją w 5 minut. 1 TB ruchu w zestawie.

Wypróbuj za darmo


Powiązane artykuły