2009-09-18 15 views
11

Mam tę aplikację, która wymaga trochę pamięci. Podczas gdy już profiluję samą aplikację i przycinam rzeczy, sama JVM wydaje mi się zbyt rozdęta na naszej najbardziej pracowitej instancji. (Niższe instancje głośności nie ma tego problemu.) Szczegóły:Jaki wpływ, jeśli w ogóle, ma przełącznik -d64 na użycie pamięci rezydentnej Sun JVM?

  • Platforma:
    • RHEL4 64-bitowy (Linux 2.6.9-78.0.5.ELsmp #1 SMP x86_64)
    • Sun Java 6 (Java HotSpot(TM) 64-Bit Server VM (build 10.0-b23, mixed mode))
    • Tomcat 6 z -d64 w startup.sh
  • Moja aplikacja internetowa ma obecnie kod, który w produkcji wymaga korzyści działa 64-bit.
  • Zauważyłem, że po pewnym czasie (w tygodniu) rozmiar pamięci rezydentnej maszyny JVM (zgodnie z górą) wynosi trzykrotnie rozmiar ustawienia my -Xmx.
  • wielkość pamięci nieulotnej stos, itd są stosunkowo trywialne, jedynie pojedynczy cyfrowy procentowa wielkość hałdy
  • jest tylko jedna część kodu, które wymaga 64-bitowej przestrzeni adresowej nieco

Gdybym mógł zreformować zapotrzebowanie na 64-bitową maszynę JVM i upuścić przełącznik -d64, czy spowodowałoby to, że rezydualny rozmiar pamięci JVM byłby mniejszy? Innymi słowy ...

Jaki wpływ ma przełącznik -d64 na wykorzystanie pamięci rezydentnej Sun JVM?

Odpowiedz

18

Użycie przełącznika d64 przenosi JVM do trybu 64-bitowego. Technicznie, w systemie Solaris/Linux i większości Uniksów proces JVM będzie wykonywany w modelu LP64.

Model LP64 model różni się od modelu 32-bitowego (ILP32) tym, że wskaźniki mają 64-bitową szerokość w przeciwieństwie do wskaźników 32-bitowych. W przypadku JVM pozwala to na większą adresowalność pamięci, ale oznacza także, że rozmiar zajmowany przez same odwołania do obiektów podwoił się. Tak więc istnieje większe nadęcie dla tej samej liczby obiektów w danym momencie w 32-bitowej maszynie JVM i 64-bitowej.

Inną rzeczą, o której często zapomina się, jest rozmiar samych instrukcji. W 64-bitowej maszynie JVM wielkość instrukcji będzie zajmować natywny rozmiar rejestru maszynowego.

Jeśli jednak używasz compressed object pointers w środowisku 64-bitowym, JVM będzie kodować i dekodować wskaźniki, gdy tylko jest to możliwe, dla sterty większych niż 4 GB. Krótko mówiąc, podczas korzystania ze skompresowanych wskaźników JVM stara się maksymalnie wykorzystać 32-bitowe wartości.

Podpowiedź: Włącz flagę UseCompressedOops, używając -XX: + UseCompressedOops, aby pozbyć się niektórych nadwyżek. YMMV, ale people have reported upto 50% drop in memory bloat by using compressed oops.

EDIT

The UseCompressedOops flag is supported in version 14.0 of the Java HotSpot VM, available from Java 6 Update 14 onwards.

+0

Fantastyczna odpowiedź. Przekonałeś mnie, żebym skorygował mój kod i upuściłem -d64. Wrócę i skomentuję, jak to działa.Będę również pracował w aktualizacji JVM, aby móc wypróbować -XX: + UseCompressedOops. Dzięki. Wygrałeś * słynną na świecie nagrodę "Awesome Coder of the Month" Stu za wrzesień 2009! –

+0

Wow, nigdy nie wiedziałem, że jakiś google-fu wyjaśniłby taką reakcję. Dzięki, jestem zaskoczony twoją odpowiedzią! Przy okazji, jeśli uda ci się utrzymać stertę mniejszą niż 4 GB, 64-bitowa maszyna JVM będzie zachowywać się jak 32-bitowa; nie jestem jednak pewien wpływu na wydajność. –

+0

Więcej niż Google-fo !!! Rozejrzałem się dookoła siebie i zastanawiałem się *, czy to warte wysiłku ... ale jest wiele różnych przełączników JVM i wartości, a jeśli nie to, ale przypadki i pułapki. Może być przytłaczająca, a moja potrzeba polegała na * "rób to" */* "nie przejmuj się" * odpowiedzią, której towarzyszy odpowiednie karmienie łyżką. Dzięki jeszcze raz. –