Kompaktni nizovi u Javi 9

1. Pregled

Žice u Javi su interno predstavljeni s char [] koji sadrže likove Niz. I, svaki ugljen sastoji se od 2 bajta jer Java interno koristi UTF-16.

Na primjer, ako a Niz sadrži riječ na engleskom jeziku, vodećih 8 bitova bit će 0 za svaki ugljen, kao ASCII znak može se predstaviti pomoću jednog bajta.

Mnogi likovi zahtijevaju 16 bitova da bi ih predstavili, ali statistički većina zahtijeva samo 8 bita - LATIN-1 predstavljanje znakova. Dakle, postoji opseg za poboljšanje potrošnje memorije i performansi.

Važno je i to Nizs obično zauzimaju velik dio JVM prostora gomile. I, zbog načina na koji ih JVM pohranjuje, u većini slučajeva, a Niz instanca može zauzeti dvostruko prostor zapravo treba.

U ovom ćemo članku razgovarati o opciji Stlačeni niz, uvedenoj u JDK6 i novom kompaktnom nizu, nedavno predstavljenom s JDK9. Obje su dizajnirane za optimizaciju potrošnje memorije žica na JMV-u.

2. Komprimirano Niz - Java 6

JDK 6 update 21 Performance Release predstavio je novu VM opciju:

-XX: + UseCompressedStrings

Kada je ova opcija omogućena, Žice se pohranjuju kao bajt[], umjesto char [] - čime štedite puno memorije. Međutim, ova je opcija na kraju uklonjena u JDK 7, uglavnom zato što je imala neke neželjene posljedice izvedbe.

3. Kompaktan Niz - Java 9

Java 9 donio je koncept kompaktnog Žice back.

Ovo znači to kad god stvorimo a Niz ako su svi likovi Niz može se predstaviti pomoću bajta - LATIN-1 prikaz, koristit će se bajtni niz interno, tako da se za jedan znak daje jedan bajt.

U drugim slučajevima, ako bilo kojem znaku treba više od 8 bita da bi ga predstavio, svi se znakovi pohranjuju pomoću dva bajta za svaki - UTF-16 predstavljanje.

U osnovi, kad god je to moguće, koristit će samo jedan bajt za svaki znak.

Sad je pitanje - kako će sve Niz operacije rade? Kako će razlikovati prikaze LATIN-1 i UTF-16?

Pa, da bi se riješilo ovo pitanje, izvršena je još jedna promjena u internoj provedbi Niz. Imamo završno polje koder, koji čuva ove podatke.

3.1. Niz Implementacija u Javi 9

Do sada je Niz bio je pohranjen kao char []:

privatna konačna vrijednost char [];

Od sada će to biti bajt[]:

vrijednost privatnog konačnog bajta [];

Varijabla koder:

privatni završni bajtni koder;

Gdje je koder Može biti:

statički završni bajt LATIN1 = 0; statički završni bajt UTF16 = 1;

Većina Niz operacije sada provjeravaju koder i otpremaju do određene implementacije:

javni int indexOf (int ch, int fromIndex) {return isLatin1 ()? StringLatin1.indexOf (value, ch, fromIndex): StringUTF16.indexOf (value, ch, fromIndex); } private boolean isLatin1 () {return COMPACT_STRINGS && coder == LATIN1; } 

Sa svim informacijama koje JVM trebaju spremne i dostupne, CompactString Opcija VM omogućena je prema zadanim postavkama. Da bismo ga onemogućili, možemo koristiti:

+ XX: -CompactSringings

3.2. Kako koder Djela

U Javi 9 Niz izvedba klase, duljina se izračunava kao:

public int length () {return value.length >> coder; }

Ako je Niz sadrži samo LATIN-1, vrijednost koder bit će 0 pa je duljina Niz bit će jednaka duljini bajt polja.

U drugim slučajevima, ako Niz je u UTF-16 reprezentaciji, vrijednost koder bit će 1, pa će stoga duljina biti polovica veličine stvarnog bajt polja.

Imajte na umu da su sve promjene napravljene za Compact Niz, su u internoj provedbi Niz klase i potpuno su transparentni za programere koji koriste Niz.

4. Kompaktan Žice nasuprot komprimiranom Žice

U slučaju JDK 6 Compressed Žice, glavni problem s kojim se suočio bio je taj Niz konstruktor prihvaćen samo char [] kao argument. Uz ovo, mnogi Niz operacije ovisile o char [] predstavljanje, a ne bajtni niz. Zbog toga je trebalo obaviti puno raspakiranja, što je utjecalo na performanse.

Dok u slučaju Compact Niz, održavanje dodatnog „kodera“ polja također može povećati opće troškove. Kako bi ublažili troškove koder i raspakiranje bajts do ugljens (u slučaju predstavljanja UTF-16), neke su metode intrificirane, a ASM kôd generiran od JIT kompajlera je također poboljšan.

Ova je promjena rezultirala nekim kontra-intuitivnim rezultatima. LATINSKI-1 indexOf (String) poziva intrinzičnu metodu, dok indexOf (char) ne. U slučaju UTF-16, obje ove metode nazivaju unutarnju metodu. Ovaj problem utječe samo na LATIN-1 Niz a popravit će se u budućim izdanjima.

Dakle, Kompaktan Žice su bolji od komprimiranog Žice u pogledu izvedbe.

Da biste saznali koliko je memorije spremljeno pomoću uređaja Compact Žice, analizirana su razna odlagališta hrpe Java aplikacija. I dok su rezultati uvelike ovisili o određenim aplikacijama, ukupna poboljšanja bila su gotovo uvijek značajna.

4.1. Razlika u izvedbi

Pogledajmo vrlo jednostavan primjer razlike u izvedbi između omogućavanja i onemogućavanja Compact-a Žice:

long startTime = System.currentTimeMillis (); Nizovi popisa = IntStream.rangeClosed (1, 10_000_000) .mapToObj (Integer :: toString) .collect (toList ()); long totalTime = System.currentTimeMillis () - startTime; System.out.println ("Generirano" + strings.size () + "stringovi u" + totalTime + "ms."); startTime = System.currentTimeMillis (); Dodan je niz = (String) strings.stream () .limit (100_000) .reduce ("", (l, r) -> l.toString () + r.toString ()); totalTime = System.currentTimeMillis () - startTime; System.out.println ("Stvoren niz dužine" + appended.length () + "u" + totalTime + "ms.");

Ovdje stvaramo 10 milijuna Nizs, a zatim ih dodajući na naivan način. Kada pokrenemo ovaj kod (kompaktni nizovi su omogućeni prema zadanim postavkama), dobit ćemo izlaz:

Generirano 10000000 žica u 854 ms. Stvoren niz duljine 488895 u 5130 ms.

Slično tome, ako ga pokrenemo onemogućavanjem Compact Strings koristeći: -XX: -CompactSringings opcija, izlaz je:

Generirano 10000000 žica u 936 ms. Stvoren niz duljine 488895 u 9727 ms.

Jasno je da je ovo test na površinskoj razini i ne može biti visoko reprezentativan - to je samo snimka onoga što nova opcija može učiniti za poboljšanje performansi u ovom konkretnom scenariju.

5. Zaključak

U ovom uputstvu vidjeli smo pokušaje optimizacije performansi i potrošnje memorije na JVM-u - pohranjivanjem Nizs na memorijski učinkovit način.

Kao i uvijek, cijeli je kôd dostupan na Github-u.


$config[zx-auto] not found$config[zx-overlay] not found