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 (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:
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:
// 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!
- J2ME pro pokroΦilΘ - optimalizace zdrojovΘho k≤du s profilΘrem (prßv∞ Φtete)
- J2ME pro pokroΦilΘ - znovu J2ME a Ant
- J2ME pro pokroΦilΘ - XML
- J2ME pro pokroΦilΘ - J2ME a Ant
- J2ME pro pokroΦilΘ - logovßnφ
- J2ME pro pokroΦilΘ - optimalizace zdrojovΘho k≤du