Mozno trocha pomimo, ale vela pamate sa da usetrit aj v pripade, ked potrebujeme pouzit kolekcie pre ukladanie primitivnych typov. Do standardnych java collections je mozne davat iba objekty a teda primitivne typy sa boxuju na ich objektove verzie. Toto zbytocne "zerie" vela pamate. Riesenim su primitivne kolekcie, napriklad pomocou kniznice Trove (http://trove.starlight-systems.com/).
nechápu, jakto, že tím, že se neuloží čtvrtina adresy(která je samozřejmě naprosto zbytečná - za starých dob bývalo přece paměť adresovaná segment:offset a segment byl pro celý kod/data/zásobník stejný, a tím se šetřilo prostorem) no, ale jak se může vynecháním zbytečné čtvrtiny ušetřit tři čtvrtiny místa? Ono to nebude jen šetřením v ukládání ukazatelů, že? (Buď jsem nečetl důkladně, nebo jsem měl číst ještě něco navíc)
Uklada se jen polovina adresy tj. 32 bitu namisto 64 bitu (navic posunuta o tri bity doprava). O usetreti 3/4 jsem snad nikde nepsal, jestli to z textu nekde plyne, tak je to spatne ;-)
Jinak segment:offset - to platilo za dob 16bitoveho realneho rezimu, kde to byl ale peknej opruz, protoze Intel evidentne okopiroval tuto funkcionalitu z jinych procesoru aniz by si uvedomil, ze proste 16bitu na offset je na osobnich pocitacich malo (a jiz pri navrhu programu bylo nutne uvazovat o datovem modelu tiny, large, huge atd.).
A v chranenem rezimu s 32bitovymi offsety se na pointerech nic neusetrilo, ovsem zde mel segmentovy registr (resp. po novem selektor) jiny vyznam - urcovat jak bazovou adresu a limit "segmentu", tak i pristupova prava. S flat adresami to trosku ztratilo vyznam.
No, meli jsme 32/16 bitu hybrid - vyse zminenou segmentovanou architekturu 8086. Jestli je to posledni slovo - to asi neni uplne presne, podobne jako distribuovane systemy nejsou posledni slovo nad centralizovanymi. Oboji ma sve vyhody a nevyhody, takze to patrne vznikne a bude koexistovat.
Ale napriklad takovy z/OS by bylo mozne oznacit za hybridni 32/64 bitovy operacni system.
Nemám přesné informace o reprezentaci objektů v paměti, ale pochybuju, že se dostane na 8 bytů. A i kdyby, tak takových objektů bude naprosté minimum.
S ohledem na dnešní standard zarovnání paměti na 16 bytů (aspoň na nejrozšířenější x86/x86_64 - např. kvůli movaps, ale obecné vhodnosti pro jakoukoli 16byte operaci) bych čekal, že v návrhu useknou 4 bity. Vidím samá pozitiva, nebo se pletu?
Kdysi jsem meril velikost objektu (pomoci mereni spotreby pameti) a vychazelo mi ze java.lang.Object ma 16 bajtu a kazdy object spotrebuje nasobek 8 bajtu (takhle to bylo uz na 32 bitech). Zarovnani na 8B je tam tedy vzdy, zarovani na 16B kupodivu ne.
Napada me dve negativa: Nejpis se uziva adresovani s indexem nasobenym 8, a nasobeni 16 architektura amd64 neumi. Taky by se utracelo az 8B na objekt a to muze byt uz hodne - netusim jaka je prumerna velikost objektu v prumernym programu.
Hm, díky za měření. Asi bychom u hodně malých objektů (Integer, Long, ...) přišli o pár bytů. Maximálně 1/4, to by asi nebyla taková tragédie.
To adresování mě později taky napadlo, chtělo by to vidět implementaci, třeba se Pavel Tišňovský rozepíše v dalším dílu :) V každém případě by to znamenalo, že si java musí držet nějaký zero register, bo, pokud vím, tak bázový registr je při adresování s indexem povinný.
S tim bazovym registrem mate pravdu, jeste ze mame dalsich osm pracovnich registru :-). Dekodovani adresy vypada nasledovne. Ddoufam ze je ten kod je aspon trochu citelny, je to description file pro JIT i interpretr:
// Indirect Narrow Oop Plus Offset Operand
// Note: x86 architecture doesn't support "scale * index + offset" without a base
// we can't free r12 even with Universe::narrow_oop_base() == NULL.
operand indCompressedOopOffset(rRegN reg, immL32 off) %{
predicate(UseCompressedOops && (Universe::narrow_oop_shift() == Address::times_8));
constraint(ALLOC_IN_RC(ptr_reg));
match(AddP (DecodeN reg) off);
op_cost(10);
format %{"[R12 + $reg << 3 + $off] (compressed oop addressing)" %}
interface(MEMORY_INTER) %{
base(0xc); // R12
index($reg);
scale(0x3);
disp($off);
%}
%}
Baze ma jeste vyznam pri rozpoznani typu ukazatelu, jeste se o tom nekdy zkusim rozepsat.
Asi ne, soudě podle příspěvku výše:
format %{"[R12 + $reg << 3 + $off] (compressed oop addressing)" %}
Takže je to asi tak, jak psal Maaartin, tedy místo rbx *= compress_bits a mov rax, [rbx] se píše rovnou mov rax, [r12+rbx*8]
A těch 8 (3 bity) je omezení dané platformou, z r12 si java asi udělala zero register. Ostatní řešení s násobením by asi způsobily znatelné zpomalení kódu, takže je to celkem pochopitelné.
>> Kvůli použití 32bitových ukazatelů (včetně 32bitového PC a ESP) je možné adresovat a tím pádem i využít
>> „pouze“ adresní prostor o velikosti 4 GB (232 bajtů), do něhož jsou však kromě vlastní operační paměti
>> adresovány například i oblasti paměti dostupné přes PCI sběrnici či port AGP (typicky se jedná o
>> framebuffer grafické karty) a část z tohoto rozsahu si nárokuje i samotné jádro operačního systému
>> (v případě Linuxu až 1 GB adresního rozsahu).
TO IMHO není pravda. V 32bit logickém prostoru, kam ukazují ukazatele přeci není žádný framebuffer ani paměť mapúovaná přímo harwarem. Ta je přeci mapovaná do fyzického adresního prostoru.
IMHO právě směšujete logický paměťový prostor, kde si ukousne kus samotný OS, (např. Windows celé 2GB), ale jinak nikdo nic, a fyzický, kde si taktéž kousek ukousne OS, ale hlavně velký kus hardware.Fyzický adresový prostor ale není v 32 bitovém systému omezen na 4GB, i v 32 bit systému je přístupno více fyzické paměti.
Akorát většina verzí 32bit windows zároveň zavedla umělé omezení na 4GB fyzického paměťového prostoru (prý z důvodu, že některé drivery s víc pamětí neuměly pracovat, ale asi marketing) a tak přesvědčili lidi, že je to nutné kvůli 32bitovosti...
32-bitový proces v 64bitovém prostředí Windows s podporou /3G umí alokovat až 4GB, přičemž OS zabírá jen nutné minimum v podobě knihoven wrapperů z 32 na 64 (KERNEL32.DLL, atd...) OS si nevyhrazuje žádné gigabajty, protože sám je 64bitový a může běžet naprosto mimo adresový prostor aplikace.
Je a není. Aby se dalo s HW pracovat, je třeba jej namapovat do logického adresního prostoru (neplatí vždy - třeba na klávesnici stačí IO porty, aspoň ty staré, časy se možná změnily :) ). U grafické karty bude nejspíš stačit do user space pro X, u jiného HW do kernel space (a tam to bude viset pořád).
S tím umělým omezením - některý ISA HW snad potřeboval dokonce paměť pod fyzických 16MB, je dost možné, že novější měl limit pod 4GB. Ale je samozřejmě možné, že primární problém u Windos byl s oblíbeným DWORD kódem :)
imho pokud je z userspacu pristup do framebufferu, tak prece je mapovan do logickeho adresoveho prostoru ne? hmm musim se do toho programu, ktery prisupoval do framebufferu podivat, co se vlastne volalo za funkce jadra, mozna to je reseny jak na starych VESAch 1.x pomoci vypadku stranek.
Jo. Otevře se /dev/fbX, a poté se buď zapisuje přes write, nebo se namapuje přes mmap do logického paměťového prostoru programu.
Taková by byla základní funkcionalita. Používá-li se framebuffer i na konsoli, tak to znamená, že přístup musí mít i kernel, takže je přinejmenším část mapováná i do kernel address space. Rovněž novější grafické karty už mají drivery částečně v kernelu, takže i z toho důvodu okupují i část kernel space (pokud nepřepnou kontext vždy na X-server a nepracují nad user address space - zas tak dobře se v tom neorientuju). Ale to už je trochu OT.