Pisanie Java o niskim opóźnieniu [zamknięte]

30

Czy istnieją jakieś techniki specyficzne dla Javy (rzeczy, które nie miałyby zastosowania do C ++) do pisania kodu o niskim opóźnieniu w Javie? Często widzę role Java o niskim opóźnieniu i proszą o doświadczenie w pisaniu Java o niskim opóźnieniu - co czasem wydaje się trochę oksymoronem.

Jedyne, co mogłem wymyślić, to doświadczenie z JNI, outsourcing połączeń We / Wy do kodu natywnego. Możliwe też, że używa wzorca zakłócającego, ale nie jest to faktyczna technologia.

Czy są jakieś wskazówki dla Java dotyczące pisania kodu o niskim opóźnieniu?

Wiem, że istnieje specyfikacja Java w czasie rzeczywistym, ale ostrzegam, że w czasie rzeczywistym nie jest to samo, co małe opóźnienie ....

użytkownik997112
źródło
zgaduję, że nie twórz zbyt wielu obiektów, które mogłyby uruchomić cykl zbierania
maniak ratchet
@ratchet, przypuszczam, że cokolwiek związane z siecią lub dyskiem byłoby również JNI?
user997112
Dalsze linki i prezentacje mogą Cię zainteresować Performance Java User Group plus.google.com/u/1/communities/107178245817384004088
Peter Lawrey
Dodałbym używając sun.misc.Unsafe, bezpośrednio lub pośrednio jest przydatny. Wiele niebezpiecznych metod jest traktowanych jako nieodłączne, co oznacza, że ​​są zastępowane kodem maszynowym, co pozwala uniknąć jakiegokolwiek JNI.
Peter Lawrey,
Główną techniką jest całkowite uniknięcie narzutu GC. Możesz przeczytać więcej na ten temat w tym artykule Java Development Without GC
rdalmeida

Odpowiedzi:

35

Oprócz komentarzy Martijna dodałbym:

  1. Rozgrzej JVM. Kod bajtowy zaczyna się od interpretacji dla Hotspot, a następnie zostaje skompilowany na serwerze po 10 000 obserwacji . Wielopoziomowa kompilacja może być dobrą przerwą.

  2. Ładowanie klas jest sekwencyjnym procesem obejmującym operacje we / wy na dysku. Upewnij się, że wszystkie klasy dla głównych przepływów transakcji są ładowane z góry i że nigdy nie zostaną eksmitowane z generowania perm.

  3. Postępuj zgodnie z „ zasadą pojedynczego pisarza ”, aby uniknąć sporów i skutków kolejkowania wynikających z prawa Little'a, a także przestudiuj prawo Amdhala, aby ustalić, co może być równoległe i czy warto.

  4. Modeluj swoją domenę biznesową i upewnij się, że wszystkie algorytmy to O (1) lub przynajmniej O (log n). Jest to prawdopodobnie największa przyczyna problemów z wydajnością w moim doświadczeniu. Upewnij się, że masz testy wydajności obejmujące główne przypadki.

  5. Małe opóźnienia w Javie nie ograniczają się tylko do Javy. Musisz zrozumieć cały stos, na którym wykonuje się kod. Będzie to wymagało strojenia systemu operacyjnego, wyboru odpowiedniego sprzętu, strojenia oprogramowania systemów i sterowników urządzeń dla tego sprzętu.

  6. Bądź realistą. Jeśli potrzebujesz małego opóźnienia, nie uruchamiaj hiperwizora. Upewnij się, że masz wystarczającą liczbę rdzeni dla wszystkich wątków, które muszą znajdować się w stanie umożliwiającym uruchomienie.

  7. Brak pamięci podręcznej to największy koszt wydajności. Używaj algorytmów przyjaznych dla pamięci podręcznej i ustawiających powinowactwo do rdzeni procesorów za pomocą zestawu zadań lub numactl dla JVM lub JNI dla poszczególnych wątków.

  8. Zastanów się nad alternatywną maszyną JVM, taką jak Zing od Azul, z pauzowym śmieciarzem.

  9. Co najważniejsze, zaangażuj kogoś z doświadczeniem. Pozwoli ci to zaoszczędzić tyle czasu na dłuższą metę. Bezwstydna wtyczka :-)

Opóźnienia w czasie rzeczywistym i przy niskim opóźnieniu są wyraźnie odrębnymi podmiotami, choć często ze sobą powiązane. W czasie rzeczywistym chodzi o to, aby być bardziej przewidywalnym niż szybkim. Z mojego doświadczenia wynika, że ​​JVM w czasie rzeczywistym, nawet te miękkie w czasie rzeczywistym, są wolniejsze niż normalne JVM.

Martin Thompson
źródło
2
+1 za świetną odpowiedź. Jako osoba zainteresowana takimi postami przetwarzania tx jest doskonałym punktem wyjścia do badań.
mcfinnigan,
23

Jest wiele rzeczy, o których należy pamiętać. W tej chwili jestem na Krecie z ograniczonym dostępem do sieci, więc będzie to (dość) krótkie. Poza tym nie jestem ekspertem od niskich opóźnień, ale kilku moich kolegów gra jednego w prawdziwym życiu :-).

  1. Musisz docenić Mechanical Sympathy (termin wymyślony przez Martina Thompsona ). Innymi słowy, musisz zrozumieć, co robi Twój podstawowy sprzęt. Wiedza o tym, jak procesory ładują linie pamięci podręcznej, jaka jest ich przepustowość odczytu / zapisu, szybkość pamięci głównej i wiele, wiele innych, jest bardzo ważna. Czemu? Ponieważ musisz uzasadnić, w jaki sposób kod źródłowy Java wpływa na system operacyjny / sprzęt za pośrednictwem środowiska wykonawczego JVM. Na przykład jest to sposób, w jaki zmienne pola są ułożone w kodzie źródłowym, powodując eksmisje z linii pamięci podręcznej (kosztuje ~ 150 cykli zegara), hmmm ... :-).

  2. Ogólnie rzecz biorąc, chcesz algorytmy bez blokady i wejścia / wyjścia. Nawet najlepiej zaprojektowana współbieżna aplikacja (korzystająca z blokad) jest narażona na blokowanie, blokowanie przy niskim opóźnieniu jest ogólnie złe :-).

  3. Zrozumienie alokacji obiektów i wyrzucania elementów bezużytecznych. To ogromny temat, ale w zasadzie chcesz uniknąć przerw GC (często spowodowanych naturą Stop the World różnych kolekcji GC). Specjalistyczni kolektory GC, takie jak kolektor Azul, mogą w wielu przypadkach rozwiązać ten problem po wyjęciu z pudełka, ale dla większości osób muszą zrozumieć, jak dostroić GC Sun / Oracle (CMS, G1 itp.).

  4. Hotspot JIT jest niesamowity. Dowiedz się o jego optymalizacjach, ale ogólnie rzecz biorąc, wszystkie dobre techniki OO (enkapsulacja, małe metody, możliwie jak najwięcej niezmiennych danych) pozwolą na optymalizację JIT, dając ci rodzaje poziomów wydajności, które zapewnia dobrze spreparowany kod C / C ++.

  5. Ogólna architektura systemu. Pamiętaj o sieci, o tym, w jaki sposób kolokacja maszyn jest możliwa, jeśli jesteś podłączony do centrali przez światłowód itp.

  6. Pamiętaj o wpływie rejestrowania. rejestrowanie danych binarnych lub używanie zakodowanych danych wyjściowych, które można analizować w trybie offline, jest prawdopodobnie dobrym pomysłem.

Ogólnie bardzo polecam kurs dostrajania wydajności Kirka Pepperdine'a Java [Oświadczenie: Uczę tego kursu osobiście, więc jestem stronniczy]. Zyskasz dobre omówienie różnych aspektów JVM i jego wpływu na podstawowe operacje operacyjne i sprzęt.

PS: Spróbuję powrócić do tego później i trochę go uporządkować.

Martijn Verburg
źródło
Byłoby naprawdę miło, gdyby osoby doświadczone w mechanicznej sympatii mogły dzielić się pewnymi sztuczkami pozwalającymi wykryć przekroczenie określonej granicy.
Pingowałem Twittera, aby zdobyć prawdziwych ekspertów w :-)
Martijn Verburg
Fajnie, Martin Thompson wtrącił się, warto postępować zgodnie z jego radami.
Martijn Verburg