Dlaczego narzut przy przydzielaniu obiektów / tablic w Javie?

9

Ile bajtów zajmuje tablica w Javie? Załóżmy, że jest to maszyna 64-bitowa i załóżmy, że w tablicy jest N elementów, więc wszystkie te elementy zajęłyby 2 * N, 4 * N lub 8 * N bajtów dla różnych typów tablic.

A wykład w Coursera mówi, że zajmowałby 2 * N + 24, 4 * N + 24 lub 8 * N + 24 bajtów dla tablicy N elementów, a 24 bajty nazywane są narzutem, ale nie wyjaśnił, dlaczego narzut jest potrzebne.

Również obiekty mają narzuty, które wynoszą 16 bajtów.

Czym dokładnie są te koszty ogólne? Z czego składają się te bajty 24/16?

Czy te koszty ogólne istnieją tylko w Javie? Co powiesz na C, C ++ i Python?

Gnijuohz
źródło
1
@Gnijuohz: Czy chcesz zapytać: z jakich danych składa się ten narzut?
FrustratedWithFormsDesigner
@YannisRizos: Myślę, że OP chce wiedzieć, co tak naprawdę jest w tych 24 bajtach dla tablic.
FrustratedWithFormsDesigner
@FrustratedWithFormsDesigner Ah, wydaje się, że jest to lepsza interpretacja pytania niż moja.
yannis
@YannisRizos przepraszam za moje złe podejście. Ale kiedy opublikujesz ten link, nie mogę przestać myśleć, że to jakiś sarkazm. Chyba zbyt defensywny.
Gnijuohz

Odpowiedzi:

16

Każdy obiekt Java ma nagłówek zawierający informacje ważne dla JVM. Najważniejsze jest odwołanie do klasy obiektu (jedno słowo maszynowe), a garbage collector używa niektórych flag i zarządza synchronizacją (ponieważ każdy obiekt może być synchronizowany), który zajmuje inne słowo maszynowe (użycie słów częściowych źle wpływać na wydajność). To są 2 słowa, czyli 8 bajtów w systemach 32-bitowych i 16 bajtów w 64-bitowych. Tablice dodatkowo wymagają pola int dla długości tablicy, która jest kolejnymi 4 bajtami, być może 8 w systemach 64-bitowych.

Jeśli chodzi o inne języki:

  • C nie ma obiektów, więc oczywiście nie ma nagłówków obiektów - ale może mieć nagłówek na każdym oddzielnie przydzielonym fragmencie pamięci.

  • W C ++ nie masz wyrzucania elementów bezużytecznych i nie możesz używać dowolnych obiektów do synchronizacji, ale jeśli masz klasy z przesłoniętymi metodami, każdy obiekt ma wskaźnik do swojej vtable, podobnie jak odwołanie obiektu Java do swojej klasy. Jeśli korzystasz z inteligentnych wskaźników, które wykonują odśmiecanie, potrzebują danych porządkowych.

  • Nie wiem o Pythonie, ale jestem pewien, że potrzebuje również odwołania do klasy i informacji o sprzątaniu dla śmieciarza.

Michael Borgwardt
źródło
Obecnie w OpenJDK trwają prace nad zmniejszeniem rozmiaru nagłówków obiektów, małe, ale ważne kroki :-)
Martijn Verburg
W C ++ tylko klasy polimorficzne potrzebują tabel vt. std::pair<int, float>jest prostą klasą, która wcale nie potrzebuje vtable. W rezultacie może bardzo dobrze zmieścić się w 8 bajtach. Ponadto inteligentne wskaźniki w rzeczywistości nie muszą dodawać sprzątania. Wyraźnym kontrprzykładem jest std::unique_ptr<T>, który zwykle jest tak samo duży jak surowe T*(Unique_ptr oczywiście nie robi GC).
MSalters
4
C ma również narzut, każdy mallocprzydzielony blok pamięci potrzebuje nagłówka, który freenastępnie wykorzystuje.
herby
Co najmniej jedna biblioteka Malloc, o której wiem, używa 8-bajtowego nagłówka w systemach 32-bitowych (który ma 4-bajtową długość w dwóch zestawach 2-bajtowych wartości wartowników IIRC).
Donal Fellows