Kompakt húrok a Java 9-ben
1. Áttekintés
Húrok Java-ban belsőleg a char [] karaktereit tartalmazó Húr. És minden char 2 bájtból áll, mert A Java belsőleg használja az UTF-16-ot.
Például, ha a Húr tartalmaz egy szót angol nyelven, a vezető 8 bit mindegyikére 0 lesz char, mint ASCII karakter egyetlen bájt segítségével ábrázolható.
Sok karakter 16 bitet igényel, hogy képviselje őket, de statisztikailag a legtöbb csak 8 bitet igényel - LATIN-1 karakterábrázolás. Tehát van lehetőség a memóriafelhasználás és a teljesítmény javítására.
Ami szintén fontos, az az Húrs általában a JVM kupacterületének nagy részét foglalják el. És mivel a JVM tárolja őket, a legtöbb esetben a Húr példány kettős lehet tér valójában szüksége van rá.
Ebben a cikkben a JDK6-ban bevezetett Tömörített karakterlánc opcióról és a nemrégiben a JDK9-nel bevezetett új Compact String-ről fogunk beszélni. Mindkettőt a Strings memóriafelhasználásának optimalizálására tervezték a JMV-n.
2. Tömörítve Húr - Java 6
A JDK 6 frissítés 21 Performance Release új virtuális gép-opciót vezetett be:
-XX: + UseCompressedStrings
Ha ez az opció engedélyezve van, Húrok néven tárolják byte[], ahelyett char [] - így sok memóriát spórolhatunk meg. Ezt a lehetőséget azonban végül eltávolították a JDK 7-ből, főleg azért, mert nem kívánt teljesítmény-következményei voltak.
3. Kompakt Húr - Java 9
A Java 9 elhozta a kompakt koncepciót Húrok back.
Ez azt jelenti valahányszor létrehozunk egy Húr ha az összes karakter a Húr ábrázolható bájt - LATIN-1 ábrázolással, egy bájt tömböt használunk belsőleg olyan, hogy egy karakterhez egy bájtot adunk.
Más esetekben, ha valamelyik karakter több mint 8 bitet igényel az ábrázolásához, akkor az összes karakter mindegyikéhez két bájtot tárolunk - UTF-16 ábrázolás.
Tehát alapvetően, amikor csak lehetséges, minden karakterhez csak egy bájtot használ.
Most a kérdés az, hogy - hogyan fog az összes Húr működnek a műveletek? Hogyan különbözteti meg a LATIN-1 és az UTF-16 reprezentációkat?
Nos, ennek a kérdésnek a kezelése érdekében újabb változtatásokat hajtanak végre a program belső megvalósításában Húr. Van egy utolsó mezőnk kódoló, amely megőrzi ezeket az információkat.
3.1. Húr Megvalósítás a Java 9-ben
Eddig a Húr a-ként tárolták char []:
magán végső char [] érték;
Ezentúl ez lesz a byte[]:
privát végső bájt [] értéke;
A változó kódoló:
privát végső bájt kódoló;
Hol a kódoló lehet:
statikus végső bájt LATIN1 = 0; statikus végső bájt UTF16 = 1;
A legtöbb Húr A műveletek most ellenőrzik a kódolót, és elküldik a konkrét megvalósításnak:
public int indexOf (int ch, int fromIndex) {return isLatin1 ()? StringLatin1.indexOf (érték, ch, fromIndex): StringUTF16.indexOf (érték, ch, fromIndex); } privát logikai isLatin1 () {return COMPACT_STRINGS && coder == LATIN1; }
A JVM-nek minden szükséges információval készen és elérhetően rendelkezésre kell állnia CompactString A virtuális gép opció alapértelmezés szerint engedélyezve van. Letiltásához használhatjuk:
+ XX: -CompactStrings
3.2. Hogyan kódoló Művek
Java 9-ben Húr osztály megvalósítása, a hossza a következőképpen kerül kiszámításra:
public int length () {return value.length >> coder; }
Ha a Húr csak LATIN-1-et tartalmaz, a kódoló 0 lesz, tehát a hossza Húr megegyezik a bájt tömb hosszával.
Más esetekben, ha a Húr értéke UTF-16 reprezentációban van, értéke kódoló 1 lesz, és így a hossza a tényleges bájt tömb felének felel meg.
Vegye figyelembe, hogy a Compact minden módosítása megtörtént Húr, a belső megvalósításban vannak Húr osztályban, és teljesen átláthatóak a fejlesztők számára Húr.
4. Kompakt Húrok vs. Tömörített Húrok
JDK 6 Compressed esetén Húrok, nagy probléma volt, hogy Húr kivitelező csak elfogadott char [] érvként. Ezen kívül sok Húr műveletek függtek char [] ábrázolás és nem bájt tömb. Emiatt sok kibontást kellett elvégezni, ami befolyásolta a teljesítményt.
Míg Compact esetén Húr, az extra mező „kódoló” fenntartása szintén növelheti a rezsit. A költségek csökkentése kódoló és a kicsomagolás bytes to chars (UTF-16 reprezentáció esetén) a módszerek egy része beépített, és a JIT fordító által generált ASM kód is javult.
Ez a változás néhány ellentmondó eredményt hozott. A LATIN-1 indexOf (karakterlánc) belső módszert hív, míg az indexOf (char) nem. Az UTF-16 esetében mindkét módszer intrinsic módszert hív. Ez a kérdés csak a LATIN-1-et érinti Húr és a jövőbeni kiadásokban rögzítik.
Így kompakt Húrok jobbak, mint a Tömörítettek Húrok a teljesítmény szempontjából.
A Compact használatával megtudhatja, hogy mennyi memória van megtakarítva Húrok, elemezték a különféle Java-alkalmazások kupacait. És bár az eredmények nagymértékben függtek a konkrét alkalmazásoktól, az általános fejlesztések szinte mindig jelentősek voltak.
4.1. Különbség a teljesítményben
Lássunk egy nagyon egyszerű példát a Compact engedélyezése és letiltása közötti teljesítménybeli különbségről Húrok:
long startTime = System.currentTimeMillis (); Lista karakterláncok = IntStream.rangeClosed (1, 10_000_000) .mapToObj (Integer :: toString) .collect (toList ()); long totalTime = System.currentTimeMillis () - startTime; System.out.println ("Generated" + stringek.size () + "stringek" + totalTime + "ms." -Ben); startTime = System.currentTimeMillis (); Karakterlánc = = (Karakterlánc) húrok.stream () .limit (100_000) .reduce ("", (l, r) -> l.toString () + r.toString ()); totalTime = System.currentTimeMillis () - startTime; System.out.println ("Létrehozott hosszúsági karaktersorozat" + appended.length () + "a" + totalTime + "ms." -Ban);
Itt 10 milliót hozunk létre Húrs majd naiv módon hozzáfűzi őket. Amikor futtatjuk ezt a kódot (a kompakt karakterláncok alapértelmezés szerint engedélyezve vannak), akkor megkapjuk a kimenetet:
10000000 karakterláncot generált 854 ms alatt. Létrehozta a 488895 hosszúságú karakterláncot 5130 ms alatt.
Hasonlóképpen, ha a Compact karakterláncok letiltásával futtatjuk: -XX: -CompactStrings opció esetén a kimenet:
10000000 karakterláncot generált 936 ms alatt. 488895 hosszúságú húr készült 9727 ms alatt.
Nyilvánvaló, hogy ez egy felületi szintű teszt, és nem lehet nagyon reprezentatív - csupán egy pillanatkép arról, hogy mit tehet az új lehetőség a teljesítmény javítása érdekében ebben a konkrét forgatókönyvben.
5. Következtetés
Ebben az oktatóanyagban a JVM teljesítményének és memóriafelhasználásának optimalizálására tett kísérleteket láttuk tárolással Húrs memória-hatékony módon.
Mint mindig, a teljes kód elérhető a Githubon.