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?
Odpowiedzi:
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.
źródło
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 jeststd::unique_ptr<T>
, który zwykle jest tak samo duży jak suroweT*
(Unique_ptr oczywiście nie robi GC).malloc
przydzielony blok pamięci potrzebuje nagłówka, któryfree
następnie wykorzystuje.