Využití skrytých vlastností JDK (1)

24. 3. 2011
Doba čtení: 16 minut

Sdílet

V dnešním článku o vlastnostech JDK 6 a JDK 7 si řekneme základní informace o jedné skryté (přesněji řečeno velmi málo zdokumentované a známé) vlastnosti nových verzí JDK. Jedná se o alternativní varianty tříd HashMap, LinkedHashMap a TreeMap uložené v archivu alt-rt.jar. Tyto třídy nabízí pro některé aplikace větší výkonnost.

Obsah

1. Skryté vlastnosti Oracle JDK

2. Archivní soubory alt-rt.jar a alt-string.jar

3. Za jakých podmínek se archivy alt-rt.jar a alt-string.jar použijí?

4. Výkonnostní rozdíly mezi použitím tříd z rt.jar a alt-rt.jar

5. Zdrojový kód testovacího příkladu

6. Výsledky běhu testovacího příkladu s JDK b24

7. Podpora pro alternativní knihovny v OpenJDK (IcedTea)

8. Další vliv volby -XX:+AggressiveOpts na výkonnost aplikací

9. Odkazy na Internetu

1. Skryté vlastnosti Oracle JDK

V dnešní části seriálu o programovacím jazyku Java a jeho běhovém prostředí JRE (Java Runtime Environment) si povíme základní informace o jedné poměrně neznámé a málo využívané vlastnosti, kterou je možné využít především v proprietární Oracle JDK 6. Tato varianta JDK, nebo přesněji řečeno její běhové prostředí JRE, obsahuje, jak je to ostatně obvyklé, archivní soubor s názvem rt.jar, v němž jsou uloženy prakticky všechny třídy, rozhraní a výčtové typy tvořící aplikační programové rozhraní (API) J2SDK. Pouze několik spíše doplňkových tříd je uloženo v dalších archivech. Kromě toho však můžeme v novějších verzích JDK 6 najít i dva nové archivy, které jsou pojmenované alt-rt.jar a alt-string.jar (tento soubor najdeme až v B23). Tyto archivy jsou uloženy ve stejném podadresáři, v jakém leží i archiv rt.jar, tj. v podadresáři jre/lib/. Strukturu podadresáře jre/lib/ s výpisem všech javovských archivů (*.jar) si můžeme zobrazit například pomocí utility tree:

tree jre/lib -P "*.jar"

Struktura tohoto podadresáře je zhruba následující (povšimněte si hned prvního a druhého záznamu zvýrazněného hvězdičkami):

jre/lib
|-- alt-rt.jar ***
|-- alt-string.jar ***
|-- amd64
|   |-- headless
|   |-- jli
|   |-- motif21
|   |-- native_threads
|   |-- server
|   `-- xawt
|-- applet
|-- audio
|-- charsets.jar
|-- cmm
|-- deploy
|-- deploy.jar
|-- desktop
|   |-- applications
|   |-- icons
|   |   |-- HighContrast
|   |   |   |-- 16x16
|   |   |   |   |-- apps
|   |   |   |   `-- mimetypes
|   |   |   `-- 48x48
|   |   |       |-- apps
|   |   |       `-- mimetypes
|   |   |-- HighContrastInverse
|   |   |   |-- 16x16
|   |   |   |   |-- apps
|   |   |   |   `-- mimetypes
|   |   |   `-- 48x48
|   |   |       |-- apps
|   |   |       `-- mimetypes
|   |   |-- LowContrast
|   |   |   |-- 16x16
|   |   |   |   |-- apps
|   |   |   |   `-- mimetypes
|   |   |   `-- 48x48
|   |   |       |-- apps
|   |   |       `-- mimetypes
|   |   `-- hicolor
|   |       |-- 16x16
|   |       |   |-- apps
|   |       |   `-- mimetypes
|   |       `-- 48x48
|   |           |-- apps
|   |           `-- mimetypes
|   `-- mime
|       `-- packages
|-- endorsed
|-- ext
|   |-- dnsns.jar
|   |-- localedata.jar
|   |-- sunjce_provider.jar
|   `-- sunpkcs11.jar
|-- fonts
|-- im
|   |-- indicim.jar
|   `-- thaiim.jar
|-- images
|   |-- cursors
|   `-- icons
|-- javaws.jar
|-- jce.jar
|-- jsse.jar
|-- locale
|   |-- de
|   |   `-- LC_MESSAGES
|   |-- es
|   |   `-- LC_MESSAGES
|   |-- fr
|   |   `-- LC_MESSAGES
|   |-- it
|   |   `-- LC_MESSAGES
|   |-- ja
|   |   `-- LC_MESSAGES
|   |-- ko
|   |   `-- LC_MESSAGES
|   |-- ko.UTF-8
|   |   `-- LC_MESSAGES
|   |-- sv
|   |   `-- LC_MESSAGES
|   |-- zh
|   |   `-- LC_MESSAGES
|   |-- zh.GBK
|   |   `-- LC_MESSAGES
|   |-- zh_HK.BIG5HK
|   |   `-- LC_MESSAGES
|   |-- zh_TW
|   |   `-- LC_MESSAGES
|   `-- zh_TW.BIG5
|       `-- LC_MESSAGES
|-- management
|-- management-agent.jar
|-- oblique-fonts
|-- plugin.jar
|-- resources.jar
|-- rt.jar
|-- security
|   |-- US_export_policy.jar -> /etc/alternatives/jce_1.6.0_sun_us_export_policy.x86_64
|   `-- local_policy.jar -> /etc/alternatives/jce_1.6.0_sun_local_policy.x86_64
|-- servicetag
`-- zi
    |-- Africa
    |-- America
    |   |-- Argentina
    |   |-- Indiana
    |   |-- Kentucky
    |   `-- North_Dakota
    |-- Antarctica
    |-- Asia
    |-- Atlantic
    |-- Australia
    |-- Etc
    |-- Europe
    |-- Indian
    |-- Pacific
    `-- SystemV

98 directories, 18 files

2. Archivní soubory alt-rt.jar a alt-string.jar

Jak již název souborů alt-rt.jar a alt-string napovídá, jedná se o javovské archivy obsahující alternativní verze některých tříd tvořících standardní API J2SDK. Tyto alternativní třídy byly vytvořeny s ohledem na dosažení co nejlepšího výkonu (zejména v oficiálních benchmarcích běžících na počítačích s větším počtem procesorových jader, typicky se jedná o benchmark SPECjbb), ovšem prozatím by se tato implementace měla považovat za experimentální, i když na žádné větší problémy či chyby pravděpodobně v praxi nenarazíte (a ve skutečnosti byste ani neměli na problémy narazit, protože žádná z voleb předávaných JRE při jeho spouštění by neměla ovlivnit chování JRE do takové míry, že by došlo k chybě v některém testu kompatibility – TCK). Archiv alt-rt-jar obsahuje především binární (přeložené) podoby optimalizovaných verzí tříd HashMap, LinkedHashMap a TreeMap (tj. tříd implementujících rozhraní Map) a samozřejmě i různé pomocné třídy a rozhraní, popř. anonymní tří­dy.

Zatímco všechny tři výše zmíněné třídy uložené v archivu rt.jar neobsahují prakticky žádné optimalizace, které by zapříčinily větší složitost či menší čitelnost jejich zdrojového kódu (o čemž se ostatně můžete sami přesvědčit při pohledu do zdrojových kódů těchto tříd, například při zkoumání metod put a get), jsou v archivu alt-rt.jar umístěny třídy s optimalizovaným kódem využívajícím například vyrovnávací paměti pro ty prvky mapy, ke kterým se častěji přistupuje atd. V archivu alt-string.jar můžeme najít především upravenou variantu třídy String, která dokáže pracovat s „komprimovanými řetězci“, což je ovšem jen honosně znějící název pro běžné řetězce (které se používají například v céčku) obsahující pouze ASCII znaky. Pokud je vytvořen řetězec složený výhradně z ASCII znaků (tj. řetězec neobsahuje například znaky azbuky, nabodeníčka atd.), je uložen do pole s prvky typu byte a nikoli do pole s prvky typu char. To vede jak k úspoře paměti alokované na haldě, tak i k urychlení některých operací, protože se může pracovat s polovičním počtem bajtů pro daný řetězec.

3. Za jakých podmínek se archivy alt-rt.jar a alt-string.jar použijí?

Alternativní třídy obsažené v archivu alt-rt.jar a alt-string.jar se nepoužívají automaticky při každém startu běhového prostředí Javy. Načtou a použijí se pouze při splnění dvou podmínek. První podmínkou je, že daný archiv musí existovat, což je prozatím pouze případ Oracle JDK, nikoli však OpenJDK ani dalších variant JDK. Druhou podmínkou, která musí být splněna, je použití přepínače -XX:+AggressiveOpts při startu JRE. Pokud není alespoň jedna z těchto podmínek splněna, nevypíše se žádné chybové hlášení, ale třídy HashMap, TreeMap, String atd. se jednoduše načtou z originálního archivu rt.jar. O tom, zda se načítají původní verze tříd nebo jejich alternativní a výkonnější verze, se můžeme přesvědčit použitím přepínače -verbose při startu běhového prostředí Javy, například následujícím způsobem:

java -verbose | grep Opened

Při spuštění výše uvedeného příkazu, kde se pomocí přepínače -verbose povoluje výpis všech načítaných tříd a otevíraných archivů obsahujících tyto třídy (my ovšem většinu pro nás nepodstatných informací vyfiltrujeme), získáme následující výstup. Na různých verzích Oracle JDK a na různých platformách se mohou některé údaje odlišovat, především se to samozřejmě týká cesty k javovskému archivu:

[Opened /opt/jdk/sun/jdk1.6.0_23-x86_64/jre/lib/rt.jar]

Ovšem při použití přepínače -XX:+Aggressive­Opts, tj. při spuštění následujícího příkazu:

java -XX:+AggressiveOpts -verbose | grep Opened

můžeme z vyfiltrovaného standardního výstupu zjistit, že se skutečně načítají i alternativní knihovny uložené v archivu alt-rt.jar:

[Opened /opt/jdk/sun/jdk1.6.0_23-x86_64/jre/lib/alt-rt.jar]
[Opened /opt/jdk/sun/jdk1.6.0_23-x86_64/jre/lib/rt.jar]

4. Výkonnostní rozdíly mezi použitím tříd z rt.jar a alt-rt.jar

V předchozí kapitole jsme si řekli, že binární (přeložené) tvary tříd uložených v javovských archivech alt-rt.jar a alt-string.jar by měly být výkonnější než originální varianty těchto tříd. Ovšem toto tvrzení je samozřejmě nutné potvrdit (navíc toto tvrzení nemusí být platné za všech podmínek!), a to buď benchmarkem stávajících aplikací, například spuštěním serverové aplikace s přepínačem -XX:+AggressiveOpts s následným měřením doby odezvy této aplikace, nebo vytvořením syntetického testu zaměřeného pouze na zjištění rychlosti implementace tříd HashMap, LinkedHashMap a TreeMap. Pro účely změření výkonnosti metod Map.put() a Map.get() za stanovených podmínek jsem vytvořil jednoduchý příklad, jehož zdrojový kód lze najít v následující kapitole. V tomto příkladu se pro instance všech tří výše zmíněných tříd testuje rychlost, s jakou se do mapy vkládají objekty typu Integer, jejichž klíče jsou taktéž hodnoty typu Integer. Taktéž se zjišťuje rychlost získávání objektů z mapy metodou Map.get().

Důvod, proč je použita rostoucí číselná posloupnost klíčů, je jednoduchý – objekty jsou v hešovací mapě (instanci třídy HashMap) uspořádány na základě hešovací hodnoty (hash code) svého klíče, což je ovšem v případě instance třídy Integer přímo hodnota tohoto klíče (opět je možné se podívat do zdrojových kódů třídy Integer). Při „vhodně“ zvolené posloupnosti hodnot klíčů tedy může docházet ke kolizím, které účinnost hešovací mapy snižují. Naopak v případě použití třídy TreeMap jsou objekty v mapě uspořádány přímo na základě hodnoty klíče, přesněji řečeno na základě porovnání klíčů pomocí komparátorů. Číselná posloupnost hodnot klíčů či jejich hešovacích hodnot pak ovlivňuje interní strukturu mapy i dobu ukládání nového prvku a čtení prvku z mapy – například třída TreeMap interně využívá Red-Black stromy, jejichž struktura se při vkládání nových prvků musí měnit (viz animace dostupná na adrese http://www.ai­see.com/anim/ma­ple.htm).

5. Zdrojový kód testovacího příkladu

Ve zdrojovém kódu testovacího příkladu se používají třídy implementující rozhraní ValueGenerator, které slouží pro generování hodnot uložených v instancích třídy Integer. Klíče jsou však tvořeny jednoduchou aritmetickou posloupností celých čísel – sami si můžete vyzkoušet, jak se doba běhu aplikace změní v případě, že se pro vytváření klíčů (ne hodnot) použije odlišná posloupnost:

import java.util.Map;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Random;
import java.util.TreeMap;

interface ValueGenerator {
    public void reset();

    public Integer nextValue();
}

class SequenceGenerator implements ValueGenerator {
    private int value = 0;

    @Override
    public Integer nextValue() {
        this.value++;
        return Integer.valueOf(this.value);
    }

    @Override
    public void reset() {
        this.value = 0;
    }
}

class InverseSequenceGenerator implements ValueGenerator {
    private int value = Integer.MAX_VALUE;

    @Override
    public Integer nextValue() {
        this.value--;
        return Integer.valueOf(this.value);
    }

    @Override
    public void reset() {
        this.value = Integer.MAX_VALUE;
    }
}

class RandomSequenceGenerator implements ValueGenerator {
    private static final long SEED = 42;
    private Random rand = new Random(SEED);

    @Override
    public Integer nextValue() {
        return Integer.valueOf(this.rand.nextInt());
    }

    @Override
    public void reset() {
        this.rand.setSeed(SEED);
    }
}

public class MapBenchmark {

    private static final int EXT_LOOP_COUNT = 100;
    public static final int INT_LOOP_COUNT = 100000;

    public static long mapTest(Map<Integer, Integer> map, ValueGenerator generator) {
        long t1 = System.currentTimeMillis();
        for (int j = 0; j < EXT_LOOP_COUNT; j++) {
            map.clear();
            generator.reset();
            for (int i = 0; i < INT_LOOP_COUNT; i++) {
                Integer I = Integer.valueOf(i);
                map.put(I, generator.nextValue());
            }
            generator.reset();
            for (int i = 0; i < INT_LOOP_COUNT; i++) {
                if (!map.get(Integer.valueOf(i)).equals(generator.nextValue()))
                    throw new RuntimeException("Cannot find value");
            }
        }
        long t2 = System.currentTimeMillis();
        return t2 - t1;
    }

    private static void doTests(Map<Integer, Integer> map) {
        System.out.print(mapTest(map, new SequenceGenerator())+"\t");
        System.out.print(mapTest(map, new InverseSequenceGenerator())+"\t");
        System.out.print(mapTest(map, new RandomSequenceGenerator())+"\t");
    }

    public static void main(String[] args) {
        long t1 = System.currentTimeMillis();

        doTests(new HashMap<Integer, Integer>());
        doTests(new LinkedHashMap<Integer, Integer>());
        doTests(new TreeMap<Integer, Integer>());

        long t2 = System.currentTimeMillis();
        System.out.println(t2 - t1);
    }

}

6. Výsledky běhu testovacího příkladu s JDK b24

V této kapitole jsou uvedeny výsledky tří běhů výše popsaného testovacího příkladu. V prvním běhu nebyla volba -XX:+AggressiveOpts použita, tudíž se načetly třídy z archivu rt.jar. Ve druhém případě sice byla výše zmíněná volba použita, ale soubor alt-rt.jar nebyl dostupný, takže opět došlo (bez výpisu varovného hlášení!) k načtení tříd z archivu rt.jar. Teprve ve třetím případu se díky použití volby -XX:+AggressiveOpts a dostupnosti archivu alt-rt.jar načetly alternativní verze knihoven, což mělo za daných podmínek pozitivní dopad na dobu běhu aplikace. Každý test byl spuštěný dvacetkrát, aby se omezily náhodné vlivy ostatních procesů běžících v systému.

Spuštění demonstračního příkladu bez dalších voleb (použit archiv rt.jar):

HashMap                 LinkedHashMap           TreeMap                 Total
seq    invseq random    seq     invseq  random  seq     invseq  random  time
2533    1996    2743    2549    2340    3046    5969    5861    6861    33913
2484    1991    2747    2575    2334    3051    5936    5912    6949    33996
2583    1754    2396    2415    2086    2688    5839    5801    6826    32392
2530    1992    2742    2623    2293    3113    6065    5868    6901    34134
2519    2008    2816    2780    2406    3117    6080    5870    6921    34525
2556    2063    2790    2816    2206    3067    5914    5803    6816    34036
2598    1999    2752    2970    2319    3050    5986    5923    6882    34485
2472    1981    2791    2456    2335    3070    5995    5913    6919    33939
2502    2060    2775    2818    2203    3059    5936    5847    6838    34053
2513    2046    2787    2629    2337    3122    5927    5655    6786    33816
2521    2007    2735    2969    2316    3065    5970    5939    6918    34447
2561    2005    2756    2454    2437    3203    5990    5904    6926    34251
2579    1782    2477    2623    2490    3294    5922    5778    6856    33807
2514    2053    2779    2789    2227    3072    6039    5862    6893    34233
2541    1995    2779    2584    2329    3102    5920    5901    6902    34059
2612    1997    2741    2951    2315    3045    6120    5895    6910    34592
2482    1982    2748    2497    2444    3195    5997    5684    6873    33916
2512    2048    2786    2785    2215    3063    5995    5898    6872    34186
2509    1989    2775    2970    2623    3347    5943    5707    6853    34720
2528    1986    2735    2935    2343    3054    6020    5877    6895    34387

Spuštění demonstračního příkladu s volbou -XX:+Aggressive­Opts, ovšem ve chvíli, kdy není archiv alt-rt.jar dostupný (ve výsledku je použit archiv rt.jar):

HashMap                 LinkedHashMap           TreeMap                 Total
seq    invseq random    seq     invseq  random  seq     invseq  random  time
2684    2276    2794    2791    2443    3202    5949    5905    6767    34823
2692    2254    2820    2698    2450    3210    6055    5937    6837    34969
2705    2247    2788    2785    2467    3275    5924    5807    6703    34708
2680    2237    2798    2755    2427    3163    6004    5857    6762    34690
2733    2257    2803    2787    2744    3462    5998    5859    6717    35369
2639    2246    2797    2746    2448    3198    6013    6207    6979    35281
2497    2262    2939    2825    2509    3212    5991    5798    6755    34802
2643    2258    2782    2735    2477    3244    6011    5837    6727    34721
2666    2268    2837    2474    2418    3156    6049    5927    6843    34643
2701    2239    2771    2458    2470    3222    5979    5879    6730    34459
2680    2271    2801    2559    2344    3153    5962    5824    6782    34384
2660    2259    2858    2744    2448    3263    5970    5939    6748    34894
2669    2249    2800    2715    2663    3439    5982    5785    6753    35059
2692    2253    2809    2743    2432    3240    5956    5884    6766    34780
2675    1844    2511    2463    2396    3090    5909    5807    6742    33443
2705    2243    2787    2425    2444    3267    5935    5861    6752    34425
2704    2240    2794    2804    2404    3184    5989    5811    6723    34660
2709    2289    2819    2721    2444    3269    5935    5820    6699    34710
2680    2244    2792    2524    2378    3095    5994    5785    6742    34240
2688    2284    2824    2425    2447    3206    5948    5846    6783    34465

Spuštění demonstračního příkladu s volbou -XX:+AggressiveOpts ve chvíli, kde je archiv alt-rt.jar dostupný:

HashMap                 LinkedHashMap           TreeMap                 Total
seq    invseq random    seq     invseq  random  seq     invseq  random  time
2397    1886    2527    2433    2434    3159    4709    4379    5230    29162
2390    1833    2441    2861    2748    3428    4660    4363    5209    29942
2415    1792    2472    2715    2518    3174    4688    4362    5192    29334
2412    1781    2456    2664    2385    2994    4614    4290    5188    28804
2344    1761    2428    2658    2479    3130    4806    4338    5226    29177
2473    1886    2508    2743    2487    3148    4668    4346    5202    29467
2449    1795    2403    2620    2451    3220    4665    4498    5230    29339
2499    1742    2476    2556    2398    3080    4815    4198    5353    29140
2429    1799    2472    2691    2425    3191    4663    4369    5220    29264
2453    1803    2459    2724    2431    3188    4687    4174    5240    29173
2437    1785    2374    2554    2430    3172    4638    4280    5106    28783
2374    1841    2538    2519    2382    3116    4663    4153    5236    28841
2456    1765    2414    2493    2307    2924    4563    4188    5114    28230
2357    1824    2470    2663    2465    3180    4635    4355    5237    29193
2434    1855    2446    2750    2444    3173    6883    4357    5221    31569
2466    1791    2427    2536    2488    3175    4673    4347    5251    29170
2492    1892    2506    2690    2415    3153    4694    4380    5228    29465
2471    1791    2413    2299    2410    3017    4731    4175    5228    28543
2429    1679    2369    2395    2362    2960    4595    4234    5148    28176
2364    1838    2512    2694    2426    3209    4693    4332    5188    29261

Snadno můžeme vypočítat, že zrychlení demonstračního příkladu dosahuje za daných podmínek cca 15%.

7. Podpora pro alternativní knihovny v OpenJDK (IcedTea)

Zajímavé je, že podpora pro použití alternativního archivu alt-rt.jar (nikoli však alt-string.jar) existuje i v OpenJDK a tím pádem i v IcedTea. Ostatně se není čemu divit, protože zdrojové kódy OpenJDK i proprietární Oracle JDK jsou sdílené, i když některé relativně malé části OpenJDK musely být změněny, především kvůli nekompatibilním licencím a problémům s otevřením knihoven třetích stran (tj. knihoven dodaných dalšími vývojářskými firmami společnosti Sun Microsystems a posléze Oracle). Nicméně se vraťme k oběma alternativním archivům. Ve zdrojových kódech OpenJDK lze dohledat, že se alternativní archiv alt-rt.jar skutečně při spouštění JRE hledá a popř. i načítá, a to za stejných podmínek, jako u proprietární Oracle JDK. Ostatně přesvědčit se můžeme přímo pohledem do zdrojového kódu souboru hotspot/src/sha­re/vm/runtime/ar­guments.cpp na řádky 2064 až 2077 (čísla řádků odpovídají HotSpotu verze 20, jehož zdrojové kódy lze najít na adrese http://hg.open­jdk.java.net/hsx/hsx­20/master):

  if (AggressiveOpts) {
    // Insert alt-rt.jar between user-specified bootclasspath
    // prefix and the default bootclasspath.  os::set_boot_path()
    // uses meta_index_dir as the default bootclasspath directory.
    const char* altclasses_jar = "alt-rt.jar";
    size_t altclasses_path_len = strlen(get_meta_index_dir()) + 1 +
                                 strlen(altclasses_jar);
    char* altclasses_path = NEW_C_HEAP_ARRAY(char, altclasses_path_len);
    strcpy(altclasses_path, get_meta_index_dir());
    strcat(altclasses_path, altclasses_jar);
    scp.add_suffix_to_prefix(altclasses_path);
    scp_assembly_required = true;
    FREE_C_HEAP_ARRAY(char, altclasses_path);
  }

Jediný problém spočívá v tom, že zdrojové kódy obou alternativních archivů nejsou prozatím v OpenJDK dostupné, i když je teoreticky možné (při dodržení licenčního ujednání potvrzeného při instalaci Oracle JDK) použít archivy právě z Oracle JDK.

8. Další vliv volby -XX:+AggressiveOpts na výkonnost aplikací

Použití volby -XX:+AggressiveOpts má poměrně velký vliv na výkonnost aplikací, a to i ve chvíli, kdy nejsou alternativní knihovny dostupné a/nebo používané. Vliv této volby si můžeme vyzkoušet na již mnohokrát ukazovaném příkladu ConcatTest1.java, který je upraven takovým způsobem, aby dokázal zobrazit čas konkatenace řetězce pro různé počty iterací, což má samozřejmě vliv jak na dobu trvání smyčky, tak i na obsazení haldy a zatížení správců paměti. Zdrojový tvar upraveného testovacího příkladu má tvar:

ict ve školství 24

public class ConcatTest1
{
    private static final int MAX_LOOP_COUNT = 200000;

    public static String createString(int loopCount)
    {
        String str = "";
        for (int i = 0; i < loopCount; i++)
        {
            str += i + " ";
        }
        return str;
    }

    public static void main(String[] args)
    {
        for (int loopCount = 256; loopCount < MAX_LOOP_COUNT; loopCount *= 2)
        {
            long t1 = System.currentTimeMillis();
            String str = createString(loopCount);
            //System.out.println("String length: " + str.length());
            long t2 = System.currentTimeMillis();
            System.out.println("loops: " + loopCount + "  time:" + (t2 - t1));
        }
    }
}

V následující tabulce jsou zobrazeny časy běhu „konkatenační smyčky“ v případě spuštění JVM bez volby -XX:+AggressiveOpts i s použitím této volby (výsledky byly získány s JDK b23 na platformě x86_64):

loopCount JVM bez dalších voleb Volba -XX:+AggressiveOpts Zrychlení
256 6 4 33%
512 15 8 47%
1024 25 25 0%
2048 58 74 –28% *******
4096 222 222 0%
8192 731 727 1%
16384 2617 584 78%
32768 13674 3156 77%
65536 64446 16102 75%
131072 317944 73220 77%

Vliv této volby na běh JVM si vysvětlíme příště.

9. Odkazy na Internetu

  1. The Java Compatibility Test Tools: JavaTest Harness
    http://java.sun­.com/developer/techni­calArticles/JCPto­ols2/
  2. Java HotSpot VM Options
    http://www.ora­cle.com/technet­work/java/java­se/tech/vmopti­ons-jsp-140102.html
  3. HugePages
    http://linux-mm.org/HugePages
  4. Tuning big java heap and linux huge pages
    http://www.ti­kalk.com/alm/fo­rums/tuning-big-java-heap-and-linux-huge-pages
  5. How do I set up hugepages in Red Hat Enterprise Linux 4
    http://magazi­ne.redhat.com/2007/05­/29/how-do-i-set-up-hugepages-in-red-hat-enterprise-linux-4/
  6. Java SE Tuning Tip: Large Pages on Windows and Linux
    http://blogs.sun­.com/dagastine/en­try/java_se_tu­ning_tip_large
  7. Translation lookaside buffer
    http://en.wiki­pedia.org/wiki/Tran­slation_looka­side_buffer
  8. Physical Address Extension
    http://en.wiki­pedia.org/wiki/Phy­sical_Address_Ex­tension
  9. Java HotSpot VM Options
    http://www.ora­cle.com/technet­work/java/java­se/tech/vmopti­ons-jsp-140102.html
  10. Amdahl's law
    http://en.wiki­pedia.org/wiki/Am­dahl_law
  11. Garbage collection (computer science)
    http://en.wiki­pedia.org/wiki/Gar­bage_collecti­on_(computer_sci­ence)
  12. Dr. Dobb's | G1: Java's Garbage First Garbage Collector
    http://www.drdob­bs.com/article/prin­tableArticle.jhtml?ar­ticleId=219401061­&dept_url=/ja­va/
  13. Java's garbage-collected heap
    http://www.ja­vaworld.com/ja­vaworld/jw-08–1996/jw-08-gc.html
  14. Compressed oops in the Hotspot JVM
    http://wikis.sun­.com/display/Hot­SpotInternals/Com­pressedOops
  15. 32-bit or 64-bit JVM? How about a Hybrid?
    http://blog.ju­ma.me.uk/2008/10/­14/32-bit-or-64-bit-jvm-how-about-a-hybrid/
  16. Compressed object pointers in Hotspot VM
    http://blogs.sun­.com/nike/entry/com­pressed_objec­t_pointers_in_hot­spot
  17. Java HotSpot™ Virtual Machine Performance Enhancements
    http://downlo­ad.oracle.com/ja­vase/7/docs/techno­tes/guides/vm/per­formance-enhancements-7.html
  18. Using jconsole
    http://downlo­ad.oracle.com/ja­vase/1.5.0/doc­s/guide/manage­ment/jconsole­.html
  19. jconsole – Java Monitoring and Management Console
    http://downlo­ad.oracle.com/ja­vase/1.5.0/doc­s/tooldocs/sha­re/jconsole.html
  20. Great Computer Language Shootout
    http://c2.com/cgi/wi­ki?GreatCompu­terLanguageSho­otout
  21. x86–64
    http://en.wiki­pedia.org/wiki/X86–64
  22. Physical Address Extension
    http://en.wiki­pedia.org/wiki/Phy­sical_Address_Ex­tension
  23. Java performance
    http://en.wiki­pedia.org/wiki/Ja­va_performance
  24. 1.6.0_14 (6u14)
    http://www.ora­cle.com/technet­work/java/java­se/6u14–137039.html?ssSou­rceSiteId=otncn
  25. Update Release Notes
    http://www.ora­cle.com/technet­work/java/java­se/releasenotes-136954.html
  26. Java virtual machine: 4.10 Limitations of the Java Virtual Machine
    http://java.sun­.com/docs/book­s/jvms/second_e­dition/html/Clas­sFile.doc.html#88659
  27. Java™ Platform, Standard Edition 7 Binary Snapshot Releases
    http://dlc.sun­.com.edgesuite­.net/jdk7/bina­ries/index.html
  28. Trying the prototype
    http://mail.o­penjdk.java.net/pi­permail/lambda-dev/2010-August/002179.html
  29. Better closures (for Java)
    http://blogs.sun­.com/jrose/en­try/better_clo­sures
  30. Lambdas in Java: An In-Depth Analysis
    http://www.in­foq.com/articles/lam­bdas-java-analysis
  31. Class ReflectiveOpe­rationExcepti­on
    http://downlo­ad.java.net/jdk7/doc­s/api/java/lan­g/ReflectiveO­perationExcep­tion.html
  32. Proposal: Indexing access syntax for Lists and Maps
    http://mail.o­penjdk.java.net/pi­permail/coin-dev/2009-March/001108.html
  33. Proposal: Elvis and Other Null-Safe Operators
    http://mail.o­penjdk.java.net/pi­permail/coin-dev/2009-March/000047.html
  34. Java 7 : Oracle pushes a first version of closures
    http://www.bap­tiste-wicht.com/2010/05­/oracle-pushes-a-first-version-of-closures/
  35. Groovy: An agile dynamic language for the Java Platform
    http://groovy­.codehaus.org/O­perators
  36. Better Strategies for Null Handling in Java
    http://www.sli­deshare.net/Step­han.Schmidt/bet­ter-strategies-for-null-handling-in-java
  37. Control Flow in the Java Virtual Machine
    http://www.ar­tima.com/under­thehood/flowP­.html
  38. Java Virtual Machine
    http://en.wiki­pedia.org/wiki/Ja­va_virtual_machi­ne
  39. ==, .equals(), compareTo(), and compare()
    http://leepoin­t.net/notes-java/data/expres­sions/22compa­reobjects.html
  40. New JDK7 features
    http://openjdk­.java.net/pro­jects/jdk7/fe­atures/
  41. Project Coin: Bringing it to a Close(able)
    http://blogs.sun­.com/darcy/en­try/project_co­in_bring_close
  42. ClosableFinder source code
    http://blogs.sun­.com/darcy/re­source/Projec­tCoin/Closeable­Finder.java
  43. Joe Darcy blog about JDK
    http://blogs.sun­.com/darcy
  44. Java 7 – more dynamics
    http://www.bap­tiste-wicht.com/2010/04­/java-7-more-dynamics/
  45. ArrayList (JDK 1.4)
    http://downlo­ad.oracle.com/ja­vase/1.4.2/doc­s/api/java/util/A­rrayList.html

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.