Java Academy · Oppitunti

Pullonkaulojen tunnistaminen

Mittaa ennen optimointia.

Oppitunti 1/413 vaihetta

Pullonkaulojen tunnistaminen on ilmainen Java Academy-oppitunti CoddyKitissä. Tämä on oppitunti 1/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Java Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Java Academy-kurssilla on yhteensä 4 oppituntia.

Mitatkaa, älkää arvatko

Suorituskyvyn optimoinnin ensimmäinen sääntö: mitatkaa ennen optimointia.

Intuitio siitä, mihin Java-ohjelma käyttää aikansa, on yleensä väärässä. JIT-kääntäjä, roskienkeruu ja välimuistit tekevät mutu-arvioista epäluotettavia. Profiloikaa, etsikää todellinen kuormituskohta ja korjatkaa se.

Pullonkaulan määritelmä

Pullonkaula on järjestelmän osa, joka rajoittaa kokonaisläpimenoa tai viivettä.

Minkä tahansa muun asian optimointi ei tuota näkyvää hyötyä. Amdahlin laki täsmentää tämän: jos 90 % ajasta kuluu yhdessä metodissa, muiden 10 prosentin nopeuttaminen voi tuottaa enintään 11 prosentin parannuksen.

Viive vai läpimeno

Päättäkää, mitä optimoitte:

  • Viive — kuinka kauan yhden pyynnön käsittely kestää.
  • Läpimeno — kuinka monta pyyntöä käsitellään sekunnissa.

Ne ovat kompromissi. Eräkäsittely parantaa läpimenoa, mutta voi kasvattaa yhden pyynnön viivettä. Tietäkää tavoitteenne ennen säätämistä.

Seinäaikamittaus

Alkeellisin mittaustapa on mitata koodilohkon seinäkelloaika System.nanoTime()-metodilla.

Se sopii nopeaan järkevyystarkistukseen, mutta sisältää JIT-esilämmityksen, roskienkeruun tauot ja käyttöjärjestelmän ajoituksen aiheuttamaa kohinaa, joten yksittäisiin lukuihin on suhtauduttava varauksella.

public class Main {
    public static void main(String[] args) {
        long start = System.nanoTime();
        long sum = 0;
        for (int i = 0; i < 10_000_000; i++) sum += i;
        long elapsed = System.nanoTime() - start;
        System.out.println("Sum: " + sum);
        System.out.println("Elapsed ms: " + (elapsed / 1_000_000.0));
    }
}

Varokaa JIT-esilämmitystä

Java aloittaa tulkitsemalla tavukoodia ja kääntää sitten JIT-kääntäjällä kuumat metodit natiivikoodiksi.

Siksi metodin ensimmäiset suorituskerrat ovat paljon hitaampia kuin myöhemmät. Naiivi ajoitussilmukka mittaa pääasiassa esilämmitystä. Todelliset vertailutestit lämmittävät ensin ja mittaavat sitten vakaata tilaa — juuri näin JMH toimii puolestanne.

CPU-sidonnainen vai I/O-sidonnainen

Luokitelkaa pullonkaula:

  • CPU-sidonnainen — säikeet käyttävät aikansa laskentaan ja suorittimet ovat täysin kuormitettuja.
  • I/O-sidonnainen — säikeet odottavat levyä, verkkoa tai tietokantaa.

Profilointityökalut erottelevat nämä suorittimella käytetyksi ajaksi ja estymis-/odotusajaksi. Ratkaisu on täysin erilainen: nopeammat algoritmit tai suurempi samanaikaisuus ja harvemmat edestakaiset kutsut.

Näytteenotto ja instrumentointi

Profilointiin on kaksi strategiaa:

  • Näytteenotto — kaapataan pinon jäljityksiä säännöllisin väliajoin. Kuormitus on vähäinen, mutta tulos tilastollinen.
  • Instrumentointi — lisätään laskureita jokaiseen metodiin. Tulos on tarkka, mutta menetelmä raskas ja voi vääristää ajoituksia.

Suosikaa tuotannossa vähäisen kuormituksen näytteenottoa, kuten Java Flight Recorderia.

Muisti pullonkaulana

Usein todellinen kustannus on allokointi, ei laskenta. Liiallinen olioiden luominen käynnistää tiheän roskienkeruun, joka kuluttaa suorittimen aikaa ja lisää taukoja.

Seuratkaa allokointinopeutta ja roskienkeruuseen kuluvaa aikaa. Allokointien vähentäminen kuumassa silmukassa voittaa usein aritmetiikan mikrosäädön.

import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        // Allocation-heavy: a new String each iteration
        List<String> garbage = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            garbage.add("item-" + i);
        }
        System.out.println("Allocated " + garbage.size() + " strings");
        System.out.println("In a hot loop, this churn drives GC pressure");
    }
}

Etsikää pinon kärkeä

Näytteenottoprofileri tuottaa metodit luettelevan listan sen perusteella, kuinka usein ne esiintyivät suorittimen pinossa — tätä kutsutaan omaksi ajaksi.

Pinon huipulla oleva metodi on ehdokas. Varmistakaa kuitenkin, että se on kriittisellä polulla: taustalla lokikirjaajassa suoritettava kuormittava metodi ei välttämättä vaikuta käyttäjälle näkyvään viiveeseen.

Määrittäkää lähtötaso

Ennen muutoksia tallentakaa lähtötason mittaus realistisessa kuormassa.

Mitatkaa jokaisen muutoksen jälkeen uudelleen ja verratkaa tuloksia. Ilman lähtötasoa ette voi osoittaa optimoinnin auttaneen — ja monet ”optimoinnit” pahentavat tilannetta. Muuttakaa yhtä asiaa kerrallaan.

Profilointi realistisella kuormituksella

Joutokäynnillä olevan kannettavan tietokoneen pullonkaula ei välttämättä ole se, joka hidastaa tuotantoa.

  • Käyttäkää edustavia tietomääriä ja samanaikaisuutta.
  • Toistakaa työkuorma, jolla on käyttäjille todellisuudessa merkitystä.

Synteettiset mikrotason testit voivat ohjata menetelmään, jolla ei ole merkitystä mittakaavassa. Profiloikaa siellä, missä ongelma todella on.

Pikatarkistus

Miksi Java-metodin yksittäiset, naiivisti tehdyt System.nanoTime()-ajoitusmittaukset johtavat usein harhaan?

Yhteenveto

Pullonkaulojen löytäminen järjestelmällisesti:

  • Mitatkaa ennen optimointia; intuitio johtaa harhaan.
  • Valitkaa tavoite: latenssi tai läpimeno.
  • Luokitelkaa ongelma CPU-sidonnaiseksi tai I/O-sidonnaiseksi ja tarkkailkaa GC:tä sekä allokointia.
  • Suosikaa vähän kuormittavia näytteenottoon perustuvia profilereita.
  • Varokaa JIT-kääntäjän lämmitysvaihetta; määrittäkää vertailutaso ja muuttakaa yhtä asiaa kerrallaan.
Aloita maksutta

Opi Java tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
104
Oppitunnit
374

Usein kysytyt kysymykset

Onko oppitunti ”Pullonkaulojen tunnistaminen” ilmainen?

Kyllä – oppitunnin ”Pullonkaulojen tunnistaminen” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Java Academy-kurssin, päivitä CoddyKit PROhon. Java Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Pullonkaulojen tunnistaminen”?

Mittaa ennen optimointia. Harjoittelet Java Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Java Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Java Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 1/4.

Kuinka kauan ”Pullonkaulojen tunnistaminen”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Java Academy-oppitunnilla?

Kyllä. Jokainen Java Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Pullonkaulojen tunnistaminen
  2. Java Flight Recorder
  3. Analysointi JDK Mission Controlilla
  4. Yleiset JVM:n säätövalitsimet
← Takaisin: Java Academy