Navigace

Hlavnφ menu

 

J2ME pro pokroΦilΘ - optimalizace zdrojovΘho k≤du s profilΘrem

V jednom z p°edchozφch Φlßnk∙ jsme si teoreticky rozebrali zßkladnφ techniky, kterΘ se v J2ME b∞₧n∞ pou₧φvajφ pro optimalizaci k≤du. Pokud chceme jφt jeÜt∞ dßle, je t°eba pou₧φt n∞kter² ze specializovan²ch nßstroj∙, kter² zjistφ, jak jsou zkoumanΘ Φßsti k≤du nßroΦnΘ na provedenφ. Jeden takov² nßstroj je souΦßstφ Wireless Tooliktu a my si zde ukß₧eme, jak se s nφm pracuje.

Kdy optimalizovat?

JeÜt∞ ne₧ se vrhneme na optimalizaci, je t°eba si polo₧it otßzku, zda mß dalÜφ optimalizace smysl. V zßkladu m∙₧eme rozd∞lit nßroΦn∞jÜφ aplikace, p°edevÜφm hry, do dvou skupin, na Input-Drive a Real-Time. Do prvnφ zmφn∞nΘ skupiny pat°φ hry, kterΘ jsou zalo₧eny na vstupu u₧ivatele, typick²m p°φkladem jsou karetnφ hry nebo Üachy. Zde p°φliÜ nezßle₧φ na rychlosti, proto dalÜφ optimalizace nemß smysl. Zajφmav∞jÜφ skupinou jsou ovÜem realtime hry, kterΘ jsou typickΘ akcφ na displeji telefonu. Od t∞chto her oΦekßvßme, ₧e budou rychle reagovat na vstup od u₧ivatele, a budou mφt dostateΦn∞ vysok² framerate (FPS) pro plynulou animaci. Typick²m p°φkladem jsou arkßdy, akΦnφ hry a realtime strategie.

P°i optimalizaci je t°eba si ale uv∞domit, ₧e existujφ d∙vody proΦ neoptimalizovat:

  • optimalizacφ m∙₧eme do k≤du zanΘst chyby
  • vynalo₧enΘ ·silφ nemusφ odpovφdat v²sledku
  • n∞kterΘ techniky mohou snφ₧it mo₧nost portace na jinou platformu
  • je to zdlouhavß a mravenΦφ prßce

ProfilΘr

Jak ji₧ bylo °eΦeno v ·vodu Φlßnku, souΦßstφ KToolbaru je i nßstroj naz²van² ProfilΘr. Spus¥te KToolbar, zvolte "edit/preference" a vyberte kartu "monitoring". Najd∞te pole "Enable profiling" a zaÜkrtn∞te jej. Tφm mßte zajiÜt∞no, ₧e p°i ka₧dΘm spuÜt∞nφ naÜφ aplikace bude spuÜt∞n i profilΘr.

Ne₧ se pustφte dßle, stßhn∞te si nejprve originßlnφ zdrojovΘ k≤dy testovacφ aplikace a d∙kladn∞ si je prostudujte. Ze zdrojov²ch k≤du je vid∞t, ₧e funkΦnφ p°φnos je nulov², ale pro naÜe experimenty to nenφ podstatnΘ. Vytvo°te si nov² projekt pomocφ KToolbaru, jako default za°φzenφ vyberte "DefaultGrayPhone" a spus¥te aplikaci. Prove∩te test a zav°ete aplikaci. Pokud jste sprßvn∞ nastavili pou₧itφ profilΘru, objevφ se vßm podobnΘ okno s v²sledky.

Okno profilΘru s nam∞°en²mi daty
Okno profilΘru s nam∞°en²mi daty (plnß velikost, cca 11 kB)

V levΘ Φßsti okna se nachßzφ stromovß struktura metod, tak, jak jsou navzßjem volßny. V pravΘ Φßsti jsou nam∞°enΘ v²sledky. Aby se nßm s nimi lΘpe pracovalo, v²sledky si se°adφme. Vyberte z menu "View/Sort By/%Cycles". Jak vidφte, na prvnφch t°ech mφstech se umφstila metoda pro vykreslenφ textu na displej, kterß je souΦßsti metody paint (54 %), metoda doModel (12 %) a work (9 %). Procenta v zßvorce vyjad°ujφ nßroΦnost. Berte tato Φφsla s rezervou, proto₧e se m∞nφ v zßvislosti na rychlosti PC. My je zde pou₧ijeme jako referenΦnφ hodnoty, se kter²mi budeme porovnßvat dalÜφ v²sledky. Chceme-li tedy zrychlit naÜi aplikaci, musφme se zam∞°it na tyto t°i metody.

Optimalizace

Optimalizaci rozd∞lφme na dv∞ Φßsti - optimalizace modelu a optimalizace vykreslovßnφ.

Optimalizace vykreslovßnφ

Vykreslovßnφ mß na sv∞domφ metoda paint, kterß je definovßna takto:

public void paint(Graphics g) {
  g.setColor(BACKGROUND);
  g.fillRect(0, 0, getWidth(), getHeight());
  g.setColor(FOREGROUND);
  g.setFont(Font.getFont(Font.FACE_PROPORTIONAL,
        Font.STYLE_BOLD | Font.STYLE_ITALIC, Font.SIZE_SMALL));

  for (int i = 0; i < DRAWS; i++) {
    g.drawString(frameTime + " ms per frame",
        getRandom(getWidth()), getRandom(getHeight()),
        Graphics.TOP | Graphics.HCENTER);
  }
}

Podφvßme-li se na k≤d tΘto metody, zjistφme, ₧e smyΦka obsahuje Φßsti, kterΘ m∙₧eme napsat jako static final. Jsou to tyto Φßsti k≤du:

  • ve smyΦce se stßle volajφ metody pro zjiÜt∞nφ velikosti displeje, kter² mß konstantnφ rozm∞ry
  • neustßle se zφskßvß tent²₧ objekt fontu
  • kotva (?; anchor) umφst∞nφ textu se nem∞nφ

DalÜφm kandidßtem na optimalizaci je zφskßnφ nßhodnΘho Φφsla polohy textu na displeji. LepÜφ je, pokud nßm to pam∞¥ dovolφ, p°edpoΦφtat hodnoty do tabulek a pak z nich hodnoty jen vybφrat. P°φstup do pole je p°eci jen rychlejÜφ, ne₧ neustßlΘ zφskßvßnφ hodnot.

Nejv∞tÜφ vrßsky nßm ale d∞lß vykreslovßnφ vlastnφho textu. Z p°edchozφho Φlßnku je jasnΘ, ₧e je t°eba pou₧φt StringBuffer. Jeho napln∞nφ provedeme zavedenφm °et∞zcovΘ konstanty MESSAGE s textem, kter² budeme vykreslovat. Abychom si to trochu ulehΦili, budeme text (FPS) p°idßvat na konec tΘto konstanty. Tφm se vyhneme neustßlΘmu vytvß°enφ nebo ne zrovna jednoduchΘmu zφskßnφ v²slednΘho textu. Proto₧e se prvnφ Φßst textu nem∞nφ, postaΦφ, kdy₧ odstranφme starou Φßst a nahradφme ji novou.

P°edchozφmi optimalizacemi jsme se sice zbavili neustßlΘho vytvß°enφ objekt∙, ale jeÜt∞ to nenφ ono. Proto obsah StringBufferu vykreslφme do externφho obrßzku a ten pak p°eneseme na displej. Abychom nem∞nili obsah obrßzku neustßle, vlo₧φme jeÜt∞ podmφnku, kterß nßm zajistφ, ₧e se obrßzek zm∞nφ, jen kdy₧ se zm∞nφ hodnota FPS.

Metoda paint po optimalizaci:

public void paint(Graphics g) {
  // prepare string
  if (oldTime != frameTime) {
    buffer.delete(messageLength, buffer.length());
    buffer.append(frameTime).toString();
    messageGraphics.setColor(BACKGROUND);
    messageGraphics.fillRect(0, 0, MAX_STRING_WIDTH, MAX_STRING_HEIGHT);
    messageGraphics.setColor(FOREGROUND);
    messageGraphics.drawString(buffer.toString(), 0, 0, MESSAGE_ANCHOR);
  }

  g.setColor(BACKGROUND);
  g.fillRect(0, 0, WIDTH, HEIGHT);

  for (int i = DRAWS; --i >= 0; i++) {
    rnd = (rnd + 1) % MAX_RANDOM;
    g.drawImage(messageImage, randomX[rnd], randomY[rnd], TEXT_ANCHOR);
  }

  oldTime = frameTime;
}

Provedeme-li nynφ m∞°enφ, zjistφme, ₧e nßroΦnost vykreslovßnφ klesla p°ibli₧n∞ na polovinu, tedy 22 %. O to vφce se ale projevilo volßnφ metod work() (15 %) a doModel() (11 %).

Optimalizace modelu

Model je zalo₧en na t°ech metodßch work(), doModel(int n) a mathOperation(int a, int b, int c). Metoda work() volß ostatnφ dv∞. Nejprve bychom se m∞li zbavit globßlnφch prom∞nn²ch tφm, ₧e z nich vytvo°φme lokßlnφ prom∞nnΘ. Dßle vidφme, ₧e volßnφ metody doModel lze p°enΘst do t∞la prvnφ smyΦky.

P°i psanφ k≤du se obvykle sna₧φme, aby se Φßsti neopakovaly. Vytvo°φme tedy metodu a tu pak volßme z jin²ch Φßstφ k≤du. V kritick²ch Φßstech je ale volßnφ metody pomalΘ a je lepÜφ (pokud je to mo₧nΘ) p°enΘst jejφ t∞lo p°φmo do kritickΘho k≤du. V naÜem p°φpad∞ to je metoda mathOperation. NßÜ p°φpad nßm dßle umo₧≥uje p°epsat smyΦky tak, aby se provßd∞lo testovßnφ na nulu.

DalÜφm nezanedbateln²m faktorem je i modifikßtor metody. P°esto₧e jsou metody work a doModel takzvan∞ synchronized, m∙₧eme tento modifikßtor odstranit, proto₧e neexistuje nikdo jin² ne₧ my, kdo bude tuto metodu volat. Zde je seznam modifikßtor∙, se°azen²ch od nejpomalejÜφho k nejrychlejÜφmu:

  • synchronized
  • interface
  • normßlnφ volßnφ
  • final
  • static

Metodu work m∙₧eme jeÜt∞ optimalizovat tφm, ₧e rozepφÜeme vn∞jÜφ smyΦku, kterß je tvo°ena osmi cykly. I kdy₧ se m∙₧e zdßt, ₧e je to mrhßnφ mφstem, je t°eba si uv∞domit, ₧e v²sledn² k≤d se komprimuje a opakovanΘ Φßsti se komprimujφ zvlßÜ¥ dob°e.

V²sledky

Stßhn∞te si modifikovanΘ zdrojovΘ k≤dy a porovnejte si je s p∙vodnφmi. Otestujeme-li p∙vodnφ k≤d na reßlnΘm za°φzenφ (pou₧il jsem SE T610, firmware R3C002), zφskßme v²sledek p°ibli₧n∞ 12 405, po optimalizaci je v²sledek 5 920. Co₧ je o vφce ne₧ polovinu lepÜφ. N∞kolik obecn²ch rad pro optimalizaci:

  • Pou₧φvejte profilΘr, kter² vßm ukß₧e, kde optimalizovat.
  • Zva₧te pou₧itφ modifikßtoru metod.
  • Pou₧φvejte tabulky s p°edpoΦφtan²mi hodnotami.
  • Omezte volßnφ metod.
  • Sni₧te poΦet parametr∙ p°edßvan²ch metodßm.
  • Pou₧φvejte porovnßvßnφ na nulu.
  • Pou₧φvejte setClip() metodu pro omezenφ p°ekreslovanΘ oblasti.
  • Sna₧te se vylepÜit sv∙j algoritmus.
  • Pou₧φvejte malΘ hodnoty konstant u p°φkazu switch.

Jak vidφte, i kdy₧ je optimalizace n∞kdy nßroΦnß, je to i zßbava. Ale p°esto neoptimalizujte k≤d hned od zaΦßtku. Nejprve se zam∞°te na funkΦnost a pak provßd∞jte optimalizace. Je mo₧nΘ, ₧e n∞kterΘ metody p°epφÜete i n∞kolikrßt, ale v²sledek bude urΦit∞ stßt za to. Hodn∞ zdaru p°i optimalizaci.

J2ME pro pokroΦilΘ

Pokud to myslφte s Java 2 MicroEdition opravdu vß₧n∞, jist∞ ocenφte tento p°ehled ne zcela obligßtnφch programovacφch technik a postup∙. ╚lßnky na sebe sice p°φmo nenavazujφ, zato zvolenΘ tΘma zkoumajφ opravdu do hloubky. Tato sΘrie Φlßnk∙ dosud nebyla ukonΦena!

Prochßzka, Ji°φ (5. 10. 2004)