Zobrazit nápovědu v souboru

Transkript

Zobrazit nápovědu v souboru
Optimalizace výkonu pro
PLATFORMU ADOBE® FLASH®
Právní upozornění
Právní upozornění
Právní upozornění viz http://help.adobe.com/cs_CZ/legalnotices/index.html.
Poslední aktualizace 11.5.2012
iii
Obsah
Kapitola 1: Úvod
Základy vykonávání kódu za běhu aplikace
Vnímaný výkon versus skutečný výkon
Zaměření optimalizace
............................................................................. 1
................................................................................. 2
................................................................................................ 3
Kapitola 2: Úspora paměti
Objekty zobrazení . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
Základní typy
.......................................................................................................... 4
Opakované používání objektů
Uvolňování paměti
Používání bitmap
......................................................................................... 6
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
Filtry a dynamické odstraňování bitmap z paměti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
19
Přímé mapování MIP
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
Používání 3D efektů
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Textové objekty a paměť
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
Porovnání modelu událostí a zpětných volání
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
Kapitola 3: Minimalizace využití CPU
Vylepšení aplikace Flash Player 10.1 zaměřená na využití CPU
Režim spánku
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
Deaktivace a opětovná aktivace objektů
Události aktivace a deaktivace
Interakce myši
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
Porovnání časovačů a událostí ENTER_FRAME
Syndrom doplnění
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
Kapitola 4: Výkonnost jazyka ActionScript 3.0
Porovnání tříd Vector a Array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
Kreslicí rozhraní API
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Zachycování a probublávání událostí
Práce s obrazovými body
Regulární výrazy
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Různé optimalizace
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
Kapitola 5: Výkonnost vykreslování
Překreslování oblasti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
Obsah mimo vymezenou plochu
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
Kvalita filmu
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
Prolnutí alfa
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
Kmitočet snímků aplikace
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
Ukládání bitmapy do mezipaměti
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
Ruční ukládání bitmapy do mezipaměti
Vykreslování textových objektů
GPU
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
Poslední aktualizace 11.5.2012
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Obsah
Asynchronní operace
Průhledná okna
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
Vyhlazení tvarů vektorů
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
Kapitola 6: Optimalizace interakcí v síti
Vylepšení aplikace pro interakce v síti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
Externí obsah
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
Chyby vstupu a výstupu
Flash Remoting
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
Zbytečné síťové operace
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
Kapitola 7: Práce s médii
Video . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
StageVideo
Zvuk
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
Kapitola 8: Výkonnost databáze SQL
Návrh aplikace pro výkonnou databázi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
Optimalizace databázových souborů
Zbytečné zpracování databází za běhu
Efektivní syntaxe jazyka SQL
Výkonnost příkazů SQL
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
Kapitola 9: Porovnávání a nasazování
Porovnávání . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
Nasazování
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
Poslední aktualizace 11.5.2012
iv
1
Kapitola 1: Úvod
Aplikace Adobe® AIR® a Adobe® Flash® Player lze spouštět na mnoha platformách, mezi něž patří například stolní
počítače, mobilní zařízení, tablety a televizní zařízení. Tento dokument prostřednictvím příkladů kódu a ukázek
použití představuje osvědčené postupy určené pro vývojáře, kteří tyto aplikace nasazují. Dokument obsahuje tato
témata:
• Úspora paměti
• Minimalizace využití CPU
• Zvýšení výkonnosti jazyka ActionScript 3.0
• Zvýšení rychlosti vykreslování
• Optimalizace interakcí v síti
• Práce se zvukem a videem
• Optimalizace výkonnosti databáze SQL
• Porovnávání a nasazování aplikací
Většina těchto optimalizací se týká aplikací ve všech zařízeních, a to v běhovém prostředí AIR i běhovém prostředí
aplikace Flash Player. Jsou uvedeny také dodatky a výjimky pro konkrétní zařízení.
Některé z těchto optimalizací jsou zaměřeny na možnosti zavedené v aplikaci Flash Player 10.1 a prostředí AIR 2.5.
Řada z těchto optimalizací se však týká rovněž starších vydání prostředí AIR a aplikace Flash Player.
Základy vykonávání kódu za běhu aplikace
Klíčem k pochopení zvýšení výkonnosti aplikace je pochopení jak běh platformy Flash vykonává kód. Běhu aplikace
pracuje ve smyčce s určitými akcemi, ke kterým dochází při každém „snímku“. Snímek je v tomto případě jednoduše
blok času stanovený kmitočtem snímků, který je pro aplikaci stanoven. Množství času, které je každému snímku
přiděleno, přímo odpovídá kmitočtu snímků. Pokud například určíte kmitočet 30 snímků za sekundu, běh aplikace se
pokusí vytvořit každý snímek minimálně za jednu třicetinu sekundy.
Kmitočet snímků pro aplikaci se určuje v době vytváření. Nastavení kmitočtu snímků můžete určit pomocí nastavení
v aplikaci Adobe® Flash® Builder™ nebo Flash Professional. Počáteční kmitočet snímků můžete rovněž určit v kódu.
V aplikacích pouze s jazykem ActionScript kmitočet snímků nastavíte použitím tagu metad
[SWF(frameRate="24")] do kořenové třídy dokumentu. V jazyku MXML nastavte atribut frameRate v tagu
Application nebo WindowedApplication.
Každá smyčka snímku se skládá ze dvou fází, které jsou rozděleny do tří částí: událostí, události enterFrame a
vykreslení.
První fáze zahrnuje dvě části (události a událost enterFrame) obě z nich mohou eventuelně vést k zavolání vašeho
kódu. V první části první fáze přijdou události běhu aplikace a budou odeslány. Tyto události mohou představovat
dokončení nebo průběh asynchronních operací, například odezvu po načtení dat přes síť. Rovněž zahrnují události
z uživatelského vstupu. Protože jsou události odeslány, běh programu váš kód vykoná v posluchačích, které jste
zaregistrovali. Pokud k žádné události nedojde, běh programu počká na dokončení této fáze vykonávání bez provedení
jakékoliv akce. Běh aplikace nikdy nezrychlí kmitočet snímků z důvodu nedostatku činnosti. Pokud k událostem dojde
během jiných částí cyklu vykonávání, běh aplikace zařadí tyto události do fronty a odešle je v dalším snímku.
Poslední aktualizace 11.5.2012
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Úvod
Druhá část první fáze je událost enterFrame. Tato událost je od ostatních odlišná, protože je vždy odeslána jednou za
snímek.
Jakmile budou odeslány všechny události, začne smyčka fáze vykreslování. V tomto bodě běh aplikace vypočítá stav
všech viditelných prvků na obrazovce a vykreslí je. Tento proces se opakuje, podobně jako běžec, když běhá po závodní
dráze.
Poznámka: U událostí obsahujících vlastnost updateAfterEvent lze vynutit zpracování vykreslování okamžitě, aniž
by bylo nutné čekat na fázi vykreslování. Vlastnost updateAfterEvent ale nepoužívejte, pokud by často způsobovala
problémy s výkonem.
Nejjednodušší je si představit, že dvě fáze ve smyčce snímku trvají stejně dlouho. V tomto případě v průběhu poloviny
každého snímku běží ovladače události smyčky a kód aplikace. V průběhu druhé poloviny nastává vykreslování.
Realita je však často jiná. Někdy kód aplikace trvá více než polovinu času, který je ve snímku k dispozici, tím se zkracuje
dostupný čas, který je vyhrazený pro vykreslení. V ostatních případech, zvláště při použití složitého vizuálního obsahu,
například filtrů a režimů prolínání, vykreslování vyžaduje více než polovinu času snímku. Protože skutečný čas trvání
fází je flexibilní, smyčka snímku je běžně známa jako „pružná závodní dráha“.
Pokud kombinované operace smyčky snímku (vykonání kódu a vykreslení) trvají příliš dlouho, běh aplikace nemůže
zachovat kmitočet snímků. Snímek se prodlužuje, zabírá více času než je vyhrazeno, proto dochází ke zpoždění před
spuštěním následujícího snímku. Pokud například smyčka snímku trvá déle než jednu třicetinu sekundy, není běh
aplikace schopen aktualizovat obrazovku rychlostí 30 snímků za sekundu. Když kmitočet snímků zpomaluje, zhoršuje
se tak kvalita. V lepším případě se bude animace sekat. V horších případech se aplikace zablokuje a okno bude prázdné.
Další podrobnosti o vykonávání kódu a vykreslování modelu při běhu platformy Flash, najdete v následujících
zdrojích.
• Mentální modely přehrávače Flash – pružná závodní dráha (autor článku Ted Patrick)
• Asynchronný vykonávání kódu ActionScript (autor článku Trevor McCauley)
• Optimalizace provádění kódů, paměti a vykreslování v prostředí Adobe AIR na stránce
http://www.adobe.com/go/learn_fp_air_perf_tv_cz (Video z prezentace Seana Christmanna na konferenci MAX)
Vnímaný výkon versus skutečný výkon
Konečnými porotci, kteří hodnotí, zda má vaše aplikace dobrý výkon, jsou její uživatelé. Vývojáři mohou měřit vývoj
aplikace z hlediska doby, kterou určité operace potřebují k vykonání, nebo počtu vytvořených instancí objektů. Tyto
míry však nejsou důležité pro koncové uživatele. Uživatelé někdy měří výkon jinými kritérii. Například jestli reaguje
aplikace rychle a plynule a odpovídá rychle na vstupy? Má nepříznivý dopad na výkon systému? Odpovězte si na
následující otázky, které testují vnímaný výkon:
• Jsou animace plynulé nebo trhané?
• Vypadá video obsah plynulý nebo trhaný?
• Přehrávají se zvukové ukázky plynule, nebo se pozastavují a opět spouští?
• Bliká okno nebo je prázdné během dlouhých operací?
• Zobrazuje se text při psaní okamžitě nebo se zpožděním?
• Provede se po kliknutí nějaká akce nebo dochází ke zpoždění?
• Zvyšuje se při běhu aplikace hlučnost ventilátoru procesoru?
• Vyčerpá se baterie notebooků nebo mobilních zařízení při běhu aplikace rychle?
Poslední aktualizace 11.5.2012
2
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Úvod
• Mají ostatní aplikace při běhu této aplikace zhoršenou odezvu?
Rozdíl mezi vnímaným výkonem a skutečným výkonem je důležitý. Způsob dosažení nejlepšího vnímaného výkonu
není vždy stejný jako způsob dosažení absolutně nejrychlejšího výkonu. Dávejte pozor, aby vaše aplikace
nezpracovávala tolik kódu, že by běh aplikace nebyl schopen dostatečně často aktualizovat obrazovku a shromažďovat
vstupy od uživatele. V některých případech dosažení tohoto vyvážení vyžaduje rozdělení úlohy programu do částí tak,
aby se mezi jednotlivými částmi za běhu aktualizovala obrazovka. (Konkrétní návody najdete v části „Výkonnost
vykreslování“ na stránce 48.)
Zde popsané tipy a techniky se zaměřují na zlepšení obou záležitostí skutečné výkonnosti vykonání kódu a toho jak
uživatelé výkonnost vnímají.
Zaměření optimalizace
Některá zlepšení výkonu neznamenají znatelné zlepšení pro uživatele. Je důležité zaměřit optimalizaci výkonu do
oblastí, které jsou problematické z pohledu vaší specifické aplikace. Některé způsoby optimalizace výkonu patří mezi
všeobecné dobré postupy a lze je vždy dodržovat. Zda jsou ostatní optimalizace užitečné, závisí na potřebách vaší
aplikace a na jejích předpokládaných uživatelích. Aplikace například bude mít vždy lepší výkon, když nebudete
používat animace, videa, grafické filtry a efekty. Jedním z důvodů k použití platformy Flash k sestavování aplikací je
však schopnost práce s médii a grafikou, které umožňují vytváření bohatých působivých aplikací. Zvažte, jestli vámi
požadovaná úroveň bohatosti odpovídá výkonnostním charakteristikám počítačů a zařízení, na kterých bude vaše
aplikace fungovat.
Jednou z obecných rad je: „vyhněte se předčasné optimalizaci“. Některé optimalizace výkonnosti vyžadují zápis kódu,
který se obtížněji čte nebo je méně flexibilní. Práce s takovýmto kódem je po optimalizaci obtížnější. U těchto
optimalizací je obvykle lepší počkat, zda konkrétní část kódu má skutečně nízký výkon, předtím než provedete jeho
optimalizaci.
Zlepšení výkonu někdy zahrnuje provádění kompromisů. V ideálním případě vede snížení objemu paměti
využívaného aplikací také ke zvýšení rychlosti, kterou aplikace vykoná určitou úlohu. Tento typ ideálního zlepšení
však není vždy možný. Pokud například aplikace během nějaké operace zamrzne, řešením je často rozdělení prováděné
práce do několika snímků. Jelikož je práce rozdělená, bude dokončení celého procesu pravděpodobně trvat déle. Je ale
možné, že si uživatel tohoto delšího času nevšimne, pokud bude aplikace i nadále reagovat na vstupy a nezamrzne.
Klíčem k rozpoznání toho, co je potřeba optimalizovat a zda jsou optimalizace užitečné, je provedení testů výkonnosti.
Několik technik a tipů k testování výkonnosti je popsáno v části „Porovnávání a nasazování“ na stránce 95.
Další informace o stanovování částí aplikace, které jsou vhodné k optimalizaci, najdete v následujících zdrojích.
• Aplikace pro ladění výkonu v prostředí AIR na stránce http://www.adobe.com/go/learn_fp_goldman_tv_cz (Video
z prezentace Seana Christmanna na konferenci MAX)
• Aplikace Adobe AIR pro ladění výkonu na stránce http://www.adobe.com/go/learn_fp_air_perf_devnet_cz
(Článek z webu Adobe Developer Connection od Olivera Goldmana založený na prezentaci)
Poslední aktualizace 11.5.2012
3
4
Kapitola 2: Úspora paměti
Úsporné využívání paměti je při vývoji aplikací důležité vždy, dokonce i v případě aplikací pro stolní počítače. U
mobilních zařízení je však spotřeba paměti obzvlášť důležitá, a proto je výhodné omezit množství paměti
spotřebovaného aplikací.
Objekty zobrazení
Vyberte vhodný objekt zobrazení.
Jazyk ActionScript 3.0 obsahuje velkou skupinu objektů zobrazení. Jednou z nejjednodušších možností optimalizace
s cílem omezit spotřebu paměti je použití vhodného typu objektu zobrazení. Pro jednoduché tvary, které nejsou
interaktivní, používejte objekty Shape, pro interaktivní objekty, které nepotřebují časovou osu, používejte objekty
Sprite. Pro animaci, která využívá časovou osu, používejte objekty MovieClip. Pro svou aplikaci vybírejte zásadně
nejefektivnější typ objektu.
Následující kód zobrazuje využití paměti u různých objektů zobrazení:
trace(getSize(new Shape()));
// output: 236
trace(getSize(new Sprite()));
// output: 412
trace(getSize(new MovieClip()));
// output: 440
Metoda getSize() zobrazuje počet bajtů paměti, které spotřebuje daný objekt. Je tedy patrné, že používání více
objektů MovieClip namísto jednoduchých objektů Shape může vést k plýtvání pamětí, pokud možnosti objektu
MovieClip nejsou potřeba.
Základní typy
K testování výkonnosti kódu a určení nejefektivnějšího objektu pro danou úlohu používejte metodu getSize().
Všechny základní typy kromě objektu String využívají 4 až 8 bajtů paměti. Použitím konkrétního typu jako základního
nelze paměť optimalizovat:
Poslední aktualizace 11.5.2012
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Úspora paměti
// Primitive types
var a:Number;
trace(getSize(a));
// output: 8
var b:int;
trace(getSize(b));
// output: 4
var c:uint;
trace(getSize(c));
// output: 4
var d:Boolean;
trace(getSize(d));
// output: 4
var e:String;
trace(getSize(e));
// output: 4
Typu Number, který představuje 64bitovou hodnotu, je prostředím AVM (ActionScript Virtual Machine) přiděleno
8 bajtů, pokud mu nebyla přiřazena hodnota. Všechny ostatní základní typy jsou uloženy ve 4 bajtech.
// Primitive types
var a:Number = 8;
trace(getSize(a));
// output: 4
a = Number.MAX_VALUE;
trace(getSize(a));
// output: 8
Chování typu String je odlišné. Přidělené množství místa pro uložení závisí na délce objektu String:
var name:String;
trace(getSize(name));
// output: 4
name = "";
trace(getSize(name));
// output: 24
name = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum
has been the industry's standard dummy text ever since the 1500s, when an unknown printer took
a galley of type and scrambled it to make a type specimen book. It has survived not only five
centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It
was popularized in the 1960s with the release of Letraset sheets containing Lorem Ipsum
passages, and more recently with desktop publishing software like Aldus PageMaker including
versions of Lorem Ipsum.";
trace(getSize(name));
// output: 1172
K testování výkonnosti kódu a určení nejefektivnějšího objektu pro danou úlohu používejte metodu getSize().
Poslední aktualizace 11.5.2012
5
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Úspora paměti
Opakované používání objektů
Pokud je to možné, používejte objekty opakovaně a nevytvářejte je znovu.
Dalším jednoduchým způsobem, jak lze optimalizovat paměť, je pokud možno objekty recyklovat a nevytvářet nové.
Ve smyčce například není vhodné používat tento kód:
const MAX_NUM:int = 18;
const COLOR:uint = 0xCCCCCC;
var area:Rectangle;
for (var:int = 0; i < MAX_NUM; i++)
{
// Do not use the following code
area = new Rectangle(i,0,1,10);
myBitmapData.fillRect(area,COLOR);
}
Opakované vytvoření objektu Rectangle při každém opakování smyčky využívá více paměti a je pomalejší, protože při
každém opakování je vytvořen nový objekt. Použijte následující postup:
const MAX_NUM:int = 18;
const COLOR:uint = 0xCCCCCC;
// Create the rectangle outside the loop
var area:Rectangle = new Rectangle(0,0,1,10);
for (var:int = 0; i < MAX_NUM; i++)
{
area.x = i;
myBitmapData.fillRect(area,COLOR);
}
V předchozím příkladu byl použit objekt s relativně malým dopadem na paměť. Následující příklad demonstruje větší
úspory paměti při opakovaném používání objektu BitmapData. Následující kód určený k vytvoření efektu dlaždic
využívá nadměrné množství paměti:
Poslední aktualizace 11.5.2012
6
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Úspora paměti
var myImage:BitmapData;
var myContainer:Bitmap;
const MAX_NUM:int = 300;
for (var i:int = 0; i< MAX_NUM; i++)
{
// Create a 20 x 20 pixel bitmap, non-transparent
myImage = new BitmapData(20,20,false,0xF0D062);
// Create a container for each BitmapData instance
myContainer = new Bitmap(myImage);
// Add it to the display list
addChild(myContainer);
// Place each container
myContainer.x = (myContainer.width + 8) * Math.round(i % 20);
myContainer.y = (myContainer.height + 8) * int(i / 20);
}
Poznámka: Používáte-li kladné hodnoty, je přetypování zaokrouhlené hodnoty na celé číslo mnohem rychlejší než
použití metody Math.floor().
Následující obrázek znázorňuje výsledek uspořádání bitmap vedle sebe:
Výsledek uspořádání bitmap vedle sebe
Optimalizovaná verze vytvoří jedinou instanci objektu BitmapData, na niž odkazuje více instancí objektu Bitmap, a
má stejný výsledek:
Poslední aktualizace 11.5.2012
7
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Úspora paměti
// Create a single 20 x 20 pixel bitmap, non-transparent
var myImage:BitmapData = new BitmapData(20,20,false,0xF0D062);
var myContainer:Bitmap;
const MAX_NUM:int = 300;
for (var i:int = 0; i< MAX_NUM; i++)
{
// Create a container referencing the BitmapData instance
myContainer = new Bitmap(myImage);
// Add it to the display list
addChild(myContainer);
// Place each container
myContainer.x = (myContainer.width + 8) * Math.round(i % 20);
myContainer.y = (myContainer.height + 8) * int(i / 20);
}
Tento postup ušetří přibližně 700 kB paměti, což je u tradičního mobilního zařízení významná úspora. S každým
kontejnerem bitmapy lze pomocí vlastností třídy Bitmap manipulovat, aniž by se změnila původní instance objektu
BitmapData:
// Create a single 20 x 20 pixel bitmap, non-transparent
var myImage:BitmapData = new BitmapData(20,20,false,0xF0D062);
var myContainer:Bitmap;
const MAX_NUM:int = 300;
for (var i:int = 0; i< MAX_NUM; i++)
{
// Create a container referencing the BitmapData instance
myContainer = new Bitmap(myImage);
// Add it to the DisplayList
addChild(myContainer);
// Place each container
myContainer.x = (myContainer.width + 8) * Math.round(i % 20);
myContainer.y = (myContainer.height + 8) * int(i / 20);
// Set a specific rotation, alpha, and depth
myContainer.rotation = Math.random()*360;
myContainer.alpha = Math.random();
myContainer.scaleX = myContainer.scaleY = Math.random();
}
Následující obrázek znázorňuje výsledek transformací bitmap:
Poslední aktualizace 11.5.2012
8
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Úspora paměti
Výsledek transformací bitmap
Další témata nápovědy
„Ukládání bitmapy do mezipaměti“ na stránce 54
Sdružování objektů
Pokud je to možné, používejte sdružování objektů.
Další důležitý způsob optimalizace se nazývá sdružování objektů, které zahrnuje opakované používání objektů v
průběhu času. Během inicializace aplikace vytvoříte definovaný počet objektů a ty uložíte do fondu, jako je objekt
Array nebo Vector. Až práci s objektem dokončíte, deaktivujete jej, aby nespotřebovával prostředky CPU, a odstraníte
všechny vzájemné odkazy. Nenastavujte však odkazy na hodnotu null, protože pak by byly zpřístupněny pro čištění
uvolněné paměti. Objekt pouze vrátíte do fondu a načtete jej, až budete potřebovat nový objekt.
Opakovaným používáním objektů lze omezit nutnost vytváření instancí objektů, jež může být neúsporné. Sníží se také
pravděpodobnost spuštění nástroje pro uvolnění paměti, který může vaši aplikaci zpomalit. Následující kód ilustruje
metodu sdružování objektů:
Poslední aktualizace 11.5.2012
9
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Úspora paměti
package
{
import flash.display.Sprite;
public final class
{
private static
private static
private static
private static
private static
SpritePool
var
var
var
var
var
MAX_VALUE:uint;
GROWTH_VALUE:uint;
counter:uint;
pool:Vector.<Sprite>;
currentSprite:Sprite;
public static function initialize( maxPoolSize:uint, growthValue:uint ):void
{
MAX_VALUE = maxPoolSize;
GROWTH_VALUE = growthValue;
counter = maxPoolSize;
var i:uint = maxPoolSize;
pool = new Vector.<Sprite>(MAX_VALUE);
while( --i > -1 )
pool[i] = new Sprite();
}
public static function getSprite():Sprite
{
if ( counter > 0 )
return currentSprite = pool[--counter];
var i:uint = GROWTH_VALUE;
while( --i > -1 )
pool.unshift ( new Sprite() );
counter = GROWTH_VALUE;
return getSprite();
}
public static function disposeSprite(disposedSprite:Sprite):void
{
pool[counter++] = disposedSprite;
}
}
}
Třída SpritePool vytvoří při inicializaci aplikace fond nových objektů. Metoda getSprite() vrací instance těchto
objektů a metoda disposeSprite() je uvolňuje. Kód umožňuje, aby se fond po úplném spotřebování rozšířil. Je také
možné vytvořit fond s pevnou velikostí, kde by po spotřebování fondu nebyly přidělovány nové objekty. Snažte se
pokud možno nevytvářet nové objekty ve smyčkách. Další informace naleznete v části „Uvolňování paměti“ na
stránce 11. Následující kód využívá třídu SpritePool k získávání nových instancí:
Poslední aktualizace 11.5.2012
10
11
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Úspora paměti
const MAX_SPRITES:uint = 100;
const GROWTH_VALUE:uint = MAX_SPRITES >> 1;
const MAX_NUM:uint = 10;
SpritePool.initialize ( MAX_SPRITES,
GROWTH_VALUE );
var currentSprite:Sprite;
var container:Sprite = SpritePool.getSprite();
addChild ( container );
for ( var i:int = 0; i< MAX_NUM; i++ )
{
for ( var j:int = 0; j< MAX_NUM; j++ )
{
currentSprite = SpritePool.getSprite();
currentSprite.graphics.beginFill ( 0x990000 );
currentSprite.graphics.drawCircle ( 10, 10, 10 );
currentSprite.x = j * (currentSprite.width + 5);
currentSprite.y = i * (currentSprite.width + 5);
container.addChild ( currentSprite );
}
}
Následující kód odstraní po klepnutí myší všechny objekty zobrazení ze seznamu zobrazení a později je použije znovu
pro další úlohu:
stage.addEventListener ( MouseEvent.CLICK, removeDots );
function removeDots ( e:MouseEvent ):void
{
while (container.numChildren > 0 )
SpritePool.disposeSprite (container.removeChildAt(0) as Sprite );
}
Poznámka: Vektor fondu vždy odkazuje na objekty Sprite. Pokud byste chtěli objekt zcela odstranit z paměti, potřebovali
byste metodu dispose() ve třídě SpritePool, která by odstranila všechny zbývající odkazy.
Uvolňování paměti
Chcete-li zajistit spuštění nástroje pro uvolnění paměti, odstraňte všechny odkazy na objekty.
Ve vydané verzi aplikace Flash Player nelze nástroj pro čištění uvolněné paměti spustit přímo. Chcete-li zajistit, aby
byl objekt zpracován při čištění uvolněné paměti, odstraňte veškeré odkazy na tento objekt. Nezapomeňte, že starý
operátor delete, používaný v jazyku ActionScript 1.0 a 2.0, se v jazyku ActionScript 3.0 chová odlišně. Lze jej použít
pouze k odstranění dynamických vlastností dynamického objektu.
Poznámka: V prostředí Adobe® AIR® a v ladicí verzi aplikace Flash Player můžete nástroj pro čištění uvolněné paměti
volat přímo.
Například následující kód nastaví odkaz objektu Sprite na hodnotu null:
Poslední aktualizace 11.5.2012
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Úspora paměti
var mySprite:Sprite = new Sprite();
// Set the reference to null, so that the garbage collector removes
// it from memory
mySprite = null;
Pamatujte, že je-li objekt nastaven na hodnotu null, nemusí být nutně odstraněn z paměti. V některých případech
nástroj pro uvolnění paměti neběží, není-li množství paměti považováno za dostatečně nízké. Uvolnění paměti není
předvídatelné. Čištění uvolněné paměti se spouští na základě přidělení paměti, nikoli odstranění objektu. Když je
nástroj pro uvolnění paměti spuštěn, vyhledá grafy objektů, které dosud nebyly shromážděny. Zjistí neaktivní objekty
v grafech tím, že vyhledá objekty, které odkazují na sebe navzájem, ale aplikace je již nepoužívá. Neaktivní objekty
zjištěné tímto způsobem budou odstraněny.
Ve velkých aplikacích může tento proces značně zatěžovat CPU, negativně ovlivnit výkon a způsobit znatelné
zpomalení aplikace. Pokuste se omezit počet průchodů uvolnění paměti co nejčastějším opakovaným používáním
objektů. Také, je-li to možné, nastavujte odkazy na hodnotu null, aby nástroj pro čištění uvolněné paměti potřeboval
na vyhledávání objektů kratší čas zpracování. Považujte uvolnění paměti za pojistku a pokud možno vždy spravujte
doby životnosti objektů explicitně.
Poznámka: Nastavení odkazu objektu zobrazení na hodnotu null nezaručuje, že objekt byl deaktivován. Objekt dále
spotřebovává cykly CPU, dokud není uvolněn z paměti. Ujistěte se, že před nastavením reference objektu na hodnotu
null objekt správně deaktivujete.
Nástroj pro čištění uvolněné paměti lze spustit pomocí metody System.gc(), která je dostupná v prostředí Adobe
AIR a v ladicí verzi aplikace Flash Player. Funkce profilování obsažená v aplikaci Adobe® Flash® Builder™ umožňuje
ruční spouštění nástroje pro uvolnění paměti. Po spuštění nástroje pro uvolnění paměti lze sledovat, jakým způsobem
vaše aplikace reaguje a zda jsou objekty řádně odstraňovány z paměti.
Poznámka: Pokud byl určitý objekt použit jako posluchač události, jiný objekt na něj může odkazovat. V takovém
případě před nastavením odkazu na hodnotu null odstraňte posluchače pomocí metody removeEventListener().
Množství paměti využívané bitmapami lze snížit okamžitě. Například třída BitmapData obsahuje metodu dispose().
Další příklad kódu vytvoří instanci objektu BitmapData o velikosti 1,8 MB. Aktuální používaný objem paměti vzroste
na 1,8 MB a vlastnost System.totalMemory vrátí menší hodnotu:
trace(System.totalMemory / 1024);
// output: 43100
// Create a BitmapData instance
var image:BitmapData = new BitmapData(800, 600);
trace(System.totalMemory / 1024);
// output: 44964
V dalším kroku bude objekt BitmapData ručně odstraněn (vyřazen) z paměti a využití paměti bude opět
zkontrolováno:
Poslední aktualizace 11.5.2012
12
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Úspora paměti
trace(System.totalMemory / 1024);
// output: 43100
// Create a BitmapData instance
var image:BitmapData = new BitmapData(800, 600);
trace(System.totalMemory / 1024);
// output: 44964
image.dispose();
image = null;
trace(System.totalMemory / 1024);
// output: 43084
Přestože metoda dispose() odstraní z paměti obrazové body, odkaz musí být nastaven na hodnotu null, aby mohl
být zcela uvolněn. Když už objekt BitmapData nepotřebujete, volejte metodu dispose() a nastavte odkaz na hodnotu
null, aby se paměť okamžitě uvolnila.
Poznámka: V aplikaci Flash Player 10.1 a prostředí AIR 1.5.2 byla ve třídě System zavedena nová metoda s názvem
disposeXML(). Tato metoda umožňuje okamžitě zpřístupnit objekt XML pro čištění uvolněné paměti předáním stromu
XML jako parametru.
Další témata nápovědy
„Deaktivace a opětovná aktivace objektů“ na stránce 27
Používání bitmap
Používání vektorů namísto bitmap představuje dobrý způsob, jak ušetřit paměť. Při použití vektorů, zejména ve
velkých počtech, se však značně zvyšuje potřeba prostředků CPU či GPU. Používání bitmap je vhodné pro optimalizaci
vykreslování, protože běhové prostředí potřebuje méně prostředků procesoru ke kreslení obrazových bodů na
obrazovku než k vykreslení vektorového obsahu.
Další témata nápovědy
„Ruční ukládání bitmapy do mezipaměti“ na stránce 62
Převzorkování bitmapy
Pro lepší využití paměti jsou 32bitové neprůhledné obrazy redukovány na 16bitové, když aplikace Flash Player zjistí
16bitovou obrazovku. Toto převzorkování spotřebuje polovinu prostředků paměti a obrazy se vykreslí rychleji. Tato
funkce je dostupná pouze v aplikaci Flash Player 10.1 pro operační systém Windows Mobile.
Poznámka: Před vydáním aplikace Flash Player verze 10.1 byly všechny obrazové body vytvořené v paměti uchovávány
ve velikosti 32 bitů (4 bajtů). Jednoduché logo o velikosti 300 x 300 obrazových bodů spotřebovalo 350 kB paměti
(300*300*4/1 024). Stejné neprůhledné logo spotřebuje při použití tohoto nového chování pouze 175 kB. Pokud je logo
průhledné, nebude převzorkováno na 16 bitů a využije stejné množství paměti. Tuto funkci lze použít pouze na vložené
bitmapy a obrazy načítané za běhu (PNG, GIF, JPG).
Poslední aktualizace 11.5.2012
13
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Úspora paměti
V mobilních zařízeních může být obtížné rozpoznat obraz vykreslený v 16 bitech a stejný obraz vykreslený v 32 bitech.
U jednoduchého obrazu obsahujícího pouze několik barev neexistuje zjistitelný rozdíl. Dokonce i u složitějších obrazů
je nesnadné zjistit rozdíly. Přesto může docházet k degradaci barev při přibližování obrazu a 16bitový přechod se může
jevit jako méně plynulý než 32bitová verze.
Jediný odkaz na objekt BitmapData
Je důležité optimalizovat využití třídy BitmapData tím, že budete co nejčastěji opakovaně používat instance objektů.
V aplikaci Flash Player 10.1 a prostředí AIR 2.5 byla zavedena nová funkce pro všechny platformy nazvaná „jediný
odkaz na objekt BitmapData“. Při vytváření instancí objektu BitmapData z vloženého obrazu se pro všechny instance
objektu BitmapData použije jedna verze bitmapy. Pokud je bitmapa později upravena, je jí přidělena její vlastní
jedinečná bitmapa v paměti. Vložený obraz může pocházet z knihovny nebo tagu [Embed].
Poznámka: Stávající obsah rovněž využívá tuto novou funkci, protože v aplikaci Flash Player 10.1 a prostředí AIR 2.5
jsou bitmapy automaticky recyklovány.
Při vytváření instance vloženého obrazu se v paměti vytvoří přiřazená bitmapa. Před vydáním aplikace Flash Player
10.1 a prostředí AIR 2.5 byla každé instanci přidělena samostatná bitmapa v paměti, jak je patrné z následujícího
diagramu:
Paměť
Zobrazeno
Zdrojová bitmapa
Instance loga
Zdrojová bitmapa
Instance loga
Bitmapy v paměti před vydáním aplikace Flash Player 10.1 a prostředí AIR 2.5
Pokud je v aplikaci Flash Player 10.1 a prostředí AIR 2.5 vytvářeno více instancí téhož obrazu, pro všechny instance
objektu BitmapData je používána jediná verze bitmapy. Tuto koncepci znázorňuje následující diagram:
Poslední aktualizace 11.5.2012
14
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Úspora paměti
Paměť
Zobrazeno
Instance loga
Zdrojová bitmapa
Instance loga
Bitmapy v paměti v aplikaci Flash Player 10.1 a prostředí AIR 2.5
Tento postup značně snižuje množství paměti využívané aplikací s mnoha bitmapami. Následující kód vytvoří více
instancí symbolu Star:
const MAX_NUM:int = 18;
var star:BitmapData;
var bitmap:Bitmap;
for (var i:int = 0; i<MAX_NUM; i++)
{
for (var j:int = 0; j<MAX_NUM; j++)
{
star = new Star(0,0);
bitmap = new Bitmap(star);
bitmap.x = j * star.width;
bitmap.y = i * star.height;
addChild(bitmap)
}
}
Následující obrázek znázorňuje výsledek kódu:
Poslední aktualizace 11.5.2012
15
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Úspora paměti
Výsledek kódu pro vytvoření více instancí symbolu
Při použití aplikace Flash Player 10 například výše uvedená animace využívá přibližně 1 008 kB paměti. Při použití
aplikace Flash Player 10.1 ve stolním počítači a v mobilním zařízení tato animace využívá pouze 4 kB.
Následující kód změní jednu instanci objektu BitmapData:
const MAX_NUM:int = 18;
var star:BitmapData;
var bitmap:Bitmap;
for (var i:int = 0; i<MAX_NUM; i++)
{
for (var j:int = 0; j<MAX_NUM; j++)
{
star = new Star(0,0);
bitmap = new Bitmap(star);
bitmap.x = j * star.width;
bitmap.y = i * star.height;
addChild(bitmap)
}
}
var ref:Bitmap = getChildAt(0) as Bitmap;
ref.bitmapData.pixelDissolve(ref.bitmapData, ref.bitmapData.rect, new
Point(0,0),Math.random()*200,Math.random()*200, 0x990000);
Následující obrázek znázorňuje výsledek úpravy jedné instance symbolu Star:
Poslední aktualizace 11.5.2012
16
17
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Úspora paměti
Výsledek úpravy jedné instance
Běhové prostředí interně automaticky v paměti přiřadí a vytvoří bitmapu, aby mohly být prováděny úpravy
obrazových bodů. Po volání metody třídy BitmapData, která vede k úpravám obrazových bodů, se v paměti vytvoří
nová instance a žádné další instance nejsou aktualizovány. Tuto koncepci ilustruje následující obrázek:
Paměť
Zobrazeno
Instance loga
Zdrojová bitmapa
Instance loga
setPixel()
Zdrojová bitmapa
Instance loga
Výsledek úpravy jedné bitmapy v paměti
Při úpravě jedné hvězdy se v paměti vytvoří nová kopie. V aplikaci Flash Player 10.1 a prostředí AIR 2.5 využívá
výsledná animace pouze 8 kB paměti.
Poslední aktualizace 11.5.2012
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Úspora paměti
V předchozím příkladu lze transformovat každou bitmapu jednotlivě. Chcete-li pouze vytvořit efekt dlaždic, je
nejvhodnější metoda beginBitmapFill():
var container:Sprite = new Sprite();
var source:BitmapData = new Star(0,0);
// Fill the surface with the source BitmapData
container.graphics.beginBitmapFill(source);
container.graphics.drawRect(0,0,stage.stageWidth,stage.stageHeight);
addChild(container);
Tato metoda poskytne stejný výsledek, přičemž stačí vytvořit pouze jednu instanci objektu BitmapData. Chcete-li
hvězdy plynule otáčet, namísto přístupu ke každé instanci Star použijte objekt Matrix, který je v každém snímku
otočen. Tento objekt Matrix předejte metodě beginBitmapFill():
var container:Sprite = new Sprite();
container.addEventListener(Event.ENTER_FRAME, rotate);
var source:BitmapData = new Star(0,0);
var matrix:Matrix = new Matrix();
addChild(container);
var angle:Number = .01;
function rotate(e:Event):void
{
// Rotate the stars
matrix.rotate(angle);
// Clear the content
container.graphics.clear();
// Fill the surface with the source BitmapData
container.graphics.beginBitmapFill(source,matrix,true,true);
container.graphics.drawRect(0,0,stage.stageWidth,stage.stageHeight);
}
Při použití této metody není k vytvoření efektu potřeba smyčka ActionScript. Běhové prostředí provádí vše interně.
Následující obrázek znázorňuje výsledek transformace hvězd:
Poslední aktualizace 11.5.2012
18
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Úspora paměti
Výsledek otáčení hvězd
Při tomto postupu způsobí aktualizace původního zdrojového objektu BitmapData automatickou aktualizaci jeho
instancí kdekoli na ploše, což může být výkonná metoda. Tento postup však neumožňuje změnu velikosti jednotlivých
hvězd, jak tomu bylo v předchozím příkladu.
Poznámka: V případě použití více instancí téhož obrazu závisí kreslení na tom, zda je k původní bitmapě v paměti
přidružena třída. Pokud k bitmapě není přidružena žádná třída, obrazy jsou kresleny jako objekty Shape s bitmapovými
výplněmi.
Filtry a dynamické odstraňování bitmap z paměti
Nepoužívejte filtry, a to ani filtry zpracované nástrojem Pixel Bender.
Pokuste se omezit používání efektů, jako jsou filtry, a to včetně filtrů zpracovávaných v mobilních zařízeních
nástrojem Pixel Bender. Je-li na objekt zobrazení použit filtr, běhové prostředí vytvoří v paměti dvě bitmapy. Každá z
těchto bitmap má velikost daného objektu zobrazení. První je vytvořena jako rastrovaná verze objektu zobrazení, a ta
je pak použita k vytvoření druhé bitmapy s aplikovaným filtrem:
Poslední aktualizace 11.5.2012
19
20
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Úspora paměti
Paměť
Zobrazeno
Bitmapová verze – nefiltrovaná
Výsledek
Bitmapová verze – filtrovaná
Dvě bitmapy v paměti při použití filtru
Po změně jedné z vlastností filtru jsou obě bitmapy aktualizovány v paměti za účelem vytvoření výsledné bitmapy.
Tento proces vyžaduje určité prostředky CPU a uvedené dvě bitmapy mohou využívat významné množství paměti.
Aplikace Flash Player 10.1 a prostředí AIR 2.5 zavádí na všech platformách nové chování filtrování. Pokud není filtr
do 30 sekund změněn nebo je skrytý či mimo obrazovku, paměť využitá nefiltrovanou bitmapou se uvolní.
Tato funkce ušetří ve všech platformách polovinu paměti využité filtrem. Jako příklad uvádíme textový objekt, na který
byl použit filtr rozostření. Text v tomto případě slouží jako jednoduchá ozdoba a není upraven. Po 30 sekundách bude
nefiltrovaná bitmapa v paměti uvolněna. Ke stejnému výsledku dojde, pokud bude text po dobu 30 sekund skrytý nebo
bude mimo obrazovku. Dojde-li ke změně jedné z vlastností filtru, nefiltrovaná bitmapa v paměti bude vytvořena
znovu. Tato funkce se nazývá dynamické odstraňování bitmap z paměti. I v případě těchto optimalizací je nutné
pracovat s filtry opatrně. Během jejich úprav je vyžadován značný výkon CPU či GPU.
Osvědčený postup je filtry pokud možno emulovat pomocí bitmap vytvořených v nástroji pro tvorbu, jako například
Adobe® Photoshop®. Nepoužívejte dynamické bitmapy vytvářené za běhu v jazyce ActionScript. Používání externě
vytvořených bitmap umožňuje běhovému prostředí snížit zatížení CPU či GPU zejména v případě, že se vlastnosti
filtrů v průběhu času nemění. Je-li to možné, vytvořte veškeré požadované efekty bitmapy v nástroji pro tvorbu.
Následně bude možné bitmapu zobrazit v běhovém prostředí, aniž by bylo třeba ji jakkoli zpracovávat – takovýto
postup může být podstatně rychlejší.
Přímé mapování MIP
Mapování MIP slouží ke změně velikosti velkých obrazů, je-li to třeba.
Další nová funkce dostupná v aplikaci Flash Player 10.1 a prostředí AIR 2.5 ve všech platformách souvisí s mapováním
MIP. V aplikaci Flash Player 9 a prostředí AIR 1.0 byla zavedena funkce mapování MIP, která zvýšila kvalitu a
výkonnost převzorkovaných bitmap.
Poslední aktualizace 11.5.2012
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Úspora paměti
Poznámka: Funkci mapování MIP lze použít pouze na dynamicky načítané obrazy a na vložené bitmapy. Mapování
MIP nelze použít na objekty zobrazení, které byly filtrovány nebo uloženy do mezipaměti. Mapování MIP lze zpracovat
pouze pokud má výška a šířka bitmapy hodnotu sudého čísla. Pokud se vyskytne šířka nebo výška rovnající se lichému
číslu, mapování MIP se zastaví. Například obraz s rozměry 250 x 250 lze metodou MIP přemapovat na velikost 125 x
125, další mapování MIP ale není možné. V tomto případě má alespoň jeden rozměr hodnotu lichého čísla. Bitmapy s
rozměry, které jsou mocninami dvou, např. 256 x 256, 512 x 512, 1 024 x 1 024 atd., dosahují nejlepších výsledků.
Představte si například, že bude načten obraz o rozměrech 1 024 x 1 024 a vývojář chce rozměry obrazu změnit tak,
aby vytvořil miniaturu v galerii. Funkce mapování MIP vykreslí obraz správně, pokud byly jeho rozměry změněny s
použitím pomocných převzorkovaných verzí bitmapy jako textur. Předchozí verze běhového prostředí vytvářely
pomocné převzorkované verze bitmapy v paměti. Pokud by byl načten obraz s rozměry 1 024 x 1 024 a zobrazen ve
velikosti 64 x 64, starší verze běhového prostředí by vytvořily řadu bitmap, kde by měla každá následující bitmapa
oproti předcházející poloviční velikost. V tomto případě by byly vytvořeny bitmapy s rozměry 512 x 512, 256 x 256,
128 x 128 a 64 x 64.
Aplikace Flash Player 10.1 a prostředí AIR 2.5 nyní podporuje mapování MIP přímo z původního zdroje na
požadovanou cílovou velikost. V předchozím příkladu by byla vytvořena pouze původní bitmapa o velikosti 4 MB
(1 024 x 1 024) a bitmapa mapovaná metodou MIP o velikosti 16 kB (64 x 64).
Logika mapování MIP také spolupracuje s funkcí dynamického odstraňování bitmap z paměti. Pokud bude použita
pouze bitmapa s rozměry 64 x 64, původní bitmapa o velikosti 4 MB bude uvolněna z paměti. Pokud je nutné znovu
vytvořit mapu MIP, bude znovu načtena původní bitmapa. Budou-li vyžadovány další bitmapy různých velikostí
mapované metodou MIP, k jejich vytvoření bude použit řetězec bitmap metody mapování MIP. Pokud je například
nutné vytvořit bitmapu 1 : 8, budou posouzeny bitmapy 1 : 4, 1 : 2 a 1 : 1 s cílem zjistit, která byla do paměti načtena
jako první. Nebudou-li nalezeny žádné další verze, bude ze zdroje načtena a použita původní bitmapa 1 : 1.
Dekomprimační modul JPEG může provádět mapování MIP ve svém vlastním formátu. Toto přímé mapování MIP
umožňuje dekompresi velké bitmapy přímo do formátu mapování MIP bez načtení celého nekomprimovaného
obrazu. Vytváření mapy MIP je podstatně rychlejší a paměť použitá velkými bitmapami není přidělována a pak
uvolňována. Kvalita obrazu JPEG je srovnatelná s obecnou metodou mapování MIP.
Poznámka: Mapování MIP používejte omezeně. Přestože zlepšuje kvalitu převzorkovaných bitmap, má vliv na šířku
pásma, paměť a rychlost. V některých případech může být vhodnější použít bitmapu, jejíž velikost byla předem změněna
v externím nástroji, a poté ji importovat do aplikace. Nepoužívejte velké bitmapy, pokud je následně chcete pouze
zmenšit.
Používání 3D efektů
Zvažte možnost vytvoření 3D efektů ručně.
V aplikaci Flash Player 10 a prostředí AIR 1.5 byl zaveden modul 3D, který umožňuje aplikovat na objekty zobrazení
perspektivní transformaci. Tyto transformace lze použít pomocí vlastností rotationX a rotationY nebo metody
drawTriangles() třídy Graphics. Pomocí vlastnosti z lze také použít hloubku. Pamatujte, že každý objekt zobrazení
transformovaný perspektivní metodou je rastrován jako bitmapa, a proto vyžaduje více paměti.
Následující obrázek znázorňuje vyhlazení dosažené rastrováním při použití perspektivní transformace:
Poslední aktualizace 11.5.2012
21
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Úspora paměti
Vyhlazení způsobené perspektivní transformací
Vyhlazení je výsledkem dynamického rastrování vektorového obsahu jako bitmapy. Toto vyhlazení se provede, pokud
použijete 3D efekty ve verzi prostředí AIR a aplikace Flash Player pro stolní počítače a v prostředích AIR 2.0.1 a AIR
2.5 pro mobilní zařízení. Vyhlazení se však nepoužívá v aplikaci Flash Player pro mobilní zařízení.
Pokud můžete vytvořit 3D efekt ručně, aniž byste spoléhali na nativní rozhraní API, můžete snížit využití paměti. Nové
3D funkce zavedené v aplikaci Flash Player 10 a prostředí AIR 1.5 usnadňují mapování textur díky metodám, jako
například drawTriangles(), které provádějí mapování textur nativně.
Jako vývojář určete, zda 3D efekt, který chcete vytvořit, poskytuje lepší výkon, pokud je zpracováván prostřednictvím
nativního rozhraní API nebo ručně. Posuďte výkonnost spouštění kódu jazyka ActionScript a vykreslování a rovněž
využití paměti.
V mobilních aplikacích prostředí AIR 2.0.1 a AIR 2.5, ve kterých nastavíte vlastnost aplikace renderMode na GPU,
provádí 3D transformace GPU. Pokud je však vlastnost renderMode nastavena na CPU, provádí 3D transformace CPU,
nikoli GPU. V aplikacích Flash Player 10.1 provádí 3D transformace CPU.
Pokud provádí 3D transformace CPU, berte v úvahu, že aplikování libovolné 3D transformace na objekt zobrazení
vyžaduje dvě bitmapy v paměti. První bitmapa je zdrojová bitmapa a druhá bitmapa je verze s perspektivní
transformací. Z tohoto hlediska tedy 3D transformace fungují podobně jako filtry. Proto v případě, že 3D transformace
provádí CPU, používejte vlastnosti 3D střídmě.
Textové objekty a paměť
Pro text určený pouze ke čtení používejte modul Adobe® Flash® Text Engine, pro vstupní text používejte objekty
TextField.
V aplikaci Flash Player 10 a prostředí AIR 1.5 byl zaveden nový výkonný textový modul, Adobe Flash Text Engine
(FTE), který šetří systémovou paměť. Modul FTE je ale rozhraní API nízké úrovně, na kterém se musí nacházet další
vrstva jazyka ActionScript 3.0, jež se nachází v balíčku flash.text.engine.
Poslední aktualizace 11.5.2012
22
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Úspora paměti
Pro text určený pouze ke čtení je nejvhodnější použít modul Flash Text Engine, který nabízí nízké využití paměti a lepší
vykreslení. Pro vstupní text jsou vhodnější objekty TextField, protože je k vytvoření typických chování, například
zpracování vstupu a zalamování řádků, zapotřebí menší množství kódu jazyka ActionScript.
Další témata nápovědy
„Vykreslování textových objektů“ na stránce 68
Porovnání modelu událostí a zpětných volání
Zvažte použití jednoduchých zpětných volání namísto modelu událostí.
Model událostí jazyka ActionScript 3.0 je založen na konceptu odesílání objektů. Model událostí je objektově
orientovaný a je optimalizovaný pro opakované použití kódu. Metoda dispatchEvent() ve smyčce prochází
seznamem posluchačů a volá metodu ovladače události pro každý registrovaný objekt. Jednou z nevýhod modelu
událostí je však skutečnost, že během životnosti aplikace pravděpodobně vytvoříte velké množství objektů.
Představte si například, že potřebujete z časové osy odeslat událost, která označuje konec sekvence animace. Toto
upozornění můžete vytvořit odesláním události z konkrétního snímku v časové ose, jak ukazuje následující kód:
dispatchEvent( new Event ( Event.COMPLETE ) );
Třída Document může této události naslouchat na základě následujícího řádku kódu:
addEventListener( Event.COMPLETE, onAnimationComplete );
Přestože je takovýto přístup v pořádku, použití nativního modelu událostí může být pomalejší a využívat více paměti
než klasická funkce zpětného volání. Objekty událostí musí byt vytvořeny a vyhrazeny v paměti, což vede ke zpomalení
výkonu. Například při poslouchání události Event.ENTER_FRAME se v každém snímku vytvoří nový objekt události
pro ovladač události. U objektů zobrazení může být zpomalení výkonu obzvlášť výrazné kvůli fázi zachycení a
probublávání, jež mohou být v případě složitého seznamu zobrazení poměrně náročné.
Poslední aktualizace 11.5.2012
23
24
Kapitola 3: Minimalizace využití CPU
Další důležitou oblastí pro optimalizaci je využití CPU. Optimalizace využití CPU zvyšuje výkon a v důsledku i
životnost baterie mobilních zařízení.
Vylepšení aplikace Flash Player 10.1 zaměřená na
využití CPU
V aplikaci Flash Player 10.1 byly zavedeny dvě nové funkce, které pomáhají šetřit prostředky CPU. Tyto funkce
zahrnují pozastavení a pokračování obsahu SWF při jeho přesunutí mimo obrazovku a omezení počtu instancí
aplikace Flash Player na stránce.
Pozastavení, omezení a pokračování
Poznámka: Funkci pozastavení, omezení a pokračování nelze použít u aplikací Adobe® AIR®.
Kvůli optimalizaci využití CPU a baterie byla v aplikaci Flash Player 10.1 zavedena nová funkce, která souvisí s
neaktivními instancemi. Tato funkce umožňuje snížit využití CPU díky pozastavení souboru SWF, když se obsah
nachází mimo obrazovku, a jeho opětovnému spuštění, jakmile se obsah znovu přesune na obrazovku. Pomocí této
funkce aplikace Flash Player uvolní co nejvíce paměti odstraněním veškerých objektů, které lze vytvořit znovu, až bude
přehrávání obsahu pokračovat. Obsah je považován za mimoobrazovkový, když se celý nachází mimo obrazovku.
Umístění obsahu SWF mimo obrazovku způsobují dvě situace:
• Uživatel roluje stránku a způsobí přesunutí obsahu mimo obrazovku.
Pokud v tomto případě probíhá přehrávání videa nebo zvuku, bude přehrávání obsahu pokračovat, ale vykreslování
se zastaví. Pokud neprobíhá přehrávání zvuku ani videa, tak nastavením parametru HTML hasPriority na true
zajistěte, aby nedošlo k přerušení přehrávání nebo provádění jazyka ActionScript. Pamatujte si ale, že vykreslování
obsahu SWF se pozastaví, když je obsah mimo obrazovku nebo skrytý, bez ohledu na hodnotu parametru HTML
hasPriority.
• Dojde k otevření záložky v prohlížeči, což způsobí, že se obsah přesune do pozadí.
V tomto případě se obsah SWF zpomalí neboli omezí na 2 až 8 snímků za sekundu bez ohledu na hodnotu tagu
HTML hasPriority. Přehrávání zvuku i videa se zastaví a nebude probíhat žádné zpracovávání vykreslování až
do té doby, než se znovu zobrazí obsah SWF.
Pro aplikaci Flash Player 11.2 a novější běžící v systému Windows nebo Mac v prohlížeči pro počítač můžete ve své
aplikaci použít událost ThrottleEvent. Flash Player vyšle událost ThrottleEvent, když dojde k pozastavení, omezení
anebo pokračování.
Událost ThrottleEvent je událostí vysílání, což znamená, že ji odesílají všechny objekty EventDispatcher, které mají pro
tuto událost registrovaného posluchače. Další informace o vysílaných událostech najdete ve třídě DisplayObject.
Správa instancí
Poznámka: Funkci správy instancí nelze použít u aplikací prostředí Adobe® AIR®.
Poslední aktualizace 11.5.2012
25
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Minimalizace využití CPU
Parametr HTML hasPriority lze použít k opoždění načítání mimoobrazovkových souborů SWF.
Aplikace Flash Player 10.1 zavádí nový parametr HTML nazvaný hasPriority:
<param name="hasPriority" value="true" />
Tato funkce omezuje počet instancí aplikace Flash Player, které jsou spuštěny na stránce. Omezení počtu instancí
pomáhá šetřit prostředky CPU a baterii. Záměrem je udělit obsahu SWF určitou prioritu a tím dát některému obsahu
přednost před jiným obsahem na stránce. Uveďme jednoduchý příklad: uživatel prochází web a indexová stránka hostí
tři různé soubory SWF. Jeden z nich je viditelný, druhý je částečně viditelný na obrazovce, poslední je mimo obrazovku
a vyžaduje rolování. První dvě animace se spouštějí normálně, ale poslední je odložena, dokud nebude viditelná. Tento
scénář představuje výchozí chování v případě, že parametr hasPriority není zadán nebo je nastaven na hodnotu
false. Chcete-li zajistit spuštění souboru SWF, i kdyby byl mimo obrazovku, nastavte parametr hasPriority na
hodnotu true. Vykreslení souboru SWF, který uživatel nevidí, však bude vždy pozastaveno bez ohledu na parametr
hasPriority.
Poznámka: Pokud nastane nedostatek dostupných prostředků CPU, instance aplikace Flash Player nebudou spouštěny
automaticky ani v případě, že bude parametr hasPriority nastaven na hodnotu true. Pokud budou nové instance
vytvářeny prostřednictvím jazyka JavaScript po načtení stránky, budou příznak hasPriority ignorovat. Případný
obsah obrazových bodů 1x1 nebo 0x0 bude spuštěn, aby nedošlo k odložení pomocných souborů SWF, pokud správce
webu nevloží příznak hasPriority. Soubory SWF však lze i nadále spustit klepnutím. Toto chování se nazývá „přehrát
klepnutím“.
Následující diagramy znázorňují, jak se projevuje nastavení parametru hasPriority na různé hodnoty:
Viditelná oblast v zařízení uživatele
SWF
Parametr hasPriority
má hodnotu false
nebo neexistuje.
SWF
Parametr hasPriority
má hodnotu false
nebo neexistuje.
SWF
Parametr hasPriority má
hodnotu false nebo neexistuje.
Film ve formátu SWF spuštěn.
Film ve formátu SWF nespuštěn.
Efekty s různými hodnotami parametru hasPriority
Poslední aktualizace 11.5.2012
26
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Minimalizace využití CPU
Viditelná oblast v zařízení uživatele
SWF
Parametr hasPriority
má hodnotu false
nebo neexistuje.
SWF
Parametr hasPriority
má hodnotu false
nebo neexistuje.
SWF
Parametr hasPriority
má hodnotu true.
Film ve formátu SWF spuštěn.
Film ve formátu SWF nespuštěn.
Efekty s různými hodnotami parametru hasPriority
Režim spánku
V aplikaci Flash Player 10.1 a prostředí AIR 2.5 byla zavedena nová funkce pro mobilní zařízení, která pomáhá šetřit
výkon CPU a v důsledku toho i životnost baterií. Tato funkce se týká podsvícení používaného u mnoha mobilních
zařízení. Pokud je například uživatel, který spouští mobilní aplikaci, vyrušen a přestane používat zařízení, běhové
prostředí zjistí, kdy přejde podsvícení do režimu spánku. Při něm se sníží kmitočet snímků na 4 snímky za sekundu
(fps) a pozastaví se vykreslování. U aplikací prostředí AIR je režim spánku rovněž zahájen při přesunutí aplikace na
pozadí.
Zpracování kódu jazyka ActionScript v režimu spánku pokračuje podobně jako při nastavení vlastnosti
Stage.frameRate na hodnotu 4 fps. Krok vykreslení je ale vynechán, takže uživatel nevidí, že přehrávač běží rychlostí
4 fps. Kmitočet snímků 4 fps byl vybrán namísto nulového kmitočtu, protože umožňuje, aby všechna připojení zůstala
funkční (NetStream, Socket a NetConnection). Přepnutím na nulu by byla navázaná připojení ukončena. Obnovovací
frekvence 250 ms (4 fps) byla vybrána, protože mnoho výrobců zařízení tuto frekvenci snímků používá jako vlastní
obnovovací frekvenci. Při použití této hodnoty je kmitočet snímků běhového prostředí ponechán na stejné hodnotě,
jakou používá samotné zařízení.
Poznámka: Pokud je běhové prostředí v režimu spánku, vlastnost Stage.frameRate vrací kmitočet snímků původního
souboru SWF, nikoli 4 fps.
Poslední aktualizace 11.5.2012
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Minimalizace využití CPU
Když se podsvícení vrátí do režimu Zapnuto, vykreslování pokračuje. Kmitočet snímků se vrátí na původní hodnotu.
Jako příklad uvedeme aplikaci přehrávače médií, v níž uživatel přehrává hudbu. Pokud obrazovka přejde do režimu
spánku, běhové prostředí zareaguje podle typu přehrávaného obsahu. Dále uvádíme seznam situací s odpovídajícím
chováním běhového prostředí:
• Podsvícení přejde do režimu spánku a je přehráván jiný než audiovizuální obsah – vykreslování je pozastaveno a
kmitočet snímků je nastaven na 4 fps.
• Podsvícení přejde do režimu spánku a je přehráván audiovizuální obsah – běhové prostředí vynutí, aby bylo
podsvícení stále zapnuto a aby pokračovalo přehrávání.
• Podsvícení přejde z režimu spánku do režimu Zapnuto – běhové prostředí nastaví kmitočet snímků na původní
nastavení kmitočtu snímků souboru SWF a pokračuje ve vykreslování.
• Aplikace Flash Player je při přehrávání audiovizuálního obsahu pozastavena – aplikace Flash Player vrátí stav
podsvícení na výchozí chování systému, protože audiovizuální obsah již není přehráván.
• Mobilní zařízení přijme během přehrávání audiovizuálního obsahu telefonní hovor – vykreslování je pozastaveno
a kmitočet snímků je nastaven na 4 fps.
• Režim spánku podsvícení je v mobilním zařízení zakázán – běhové prostředí se chová normálně.
Když podsvícení přejde do režimu spánku, vykreslování se pozastaví a kmitočet snímků se zpomalí. Tato funkce šetří
prostředky CPU, ale nelze se spoléhat na to, že vytvoří skutečnou přestávku jako v herní aplikaci.
Poznámka: Při přechodu běhového prostředí do režimu spánku nebo jeho opuštění není odeslána žádná událost jazyka
ActionScript.
Deaktivace a opětovná aktivace objektů
Objekty je třeba správně deaktivovat a opětovně aktivovat pomocí událostí REMOVED_FROM_STAGE a
ADDED_TO_STAGE.
Chcete-li optimalizovat kód, vždy objekty deaktivujte a opětovně aktivujte. Deaktivace a opětovná aktivace je důležitá
u všech objektů, zejména pak u objektů zobrazení. I v případě, že již objekty zobrazení nejsou v seznamu zobrazení a
čekají na uvolnění z paměti, mohou přesto používat kód náročný na prostředky CPU. Mohou například nadále
používat konstantu Event.ENTER_FRAME. Z tohoto důvodu je velmi důležité správně deaktivovat a opětovně
aktivovat objekty pomocí událostí Event.REMOVED_FROM_STAGE a Event.ADDED_TO_STAGE. Následující příklad
představuje filmový klip přehrávaný na scéně, který lze ovládat klávesnicí:
Poslední aktualizace 11.5.2012
27
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Minimalizace využití CPU
// Listen to keyboard events
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyIsDown);
stage.addEventListener(KeyboardEvent.KEY_UP, keyIsUp);
// Create object to store key states
var keys:Dictionary = new Dictionary(true);
function keyIsDown(e:KeyboardEvent):void
{
// Remember that the key was pressed
keys[e.keyCode] = true;
if (e.keyCode==Keyboard.LEFT || e.keyCode==Keyboard.RIGHT)
{
runningBoy.play();
}
}
function keyIsUp(e:KeyboardEvent):void
{
// Remember that the key was released
keys[e.keyCode] = false;
for each (var value:Boolean in keys)
if ( value ) return;
runningBoy.stop();
}
runningBoy.addEventListener(Event.ENTER_FRAME, handleMovement);
runningBoy.stop();
var currentState:Number = runningBoy.scaleX;
var speed:Number = 15;
function handleMovement(e:Event):void
{
if (keys[Keyboard.RIGHT])
{
e.currentTarget.x += speed;
e.currentTarget.scaleX = currentState;
} else if (keys[Keyboard.LEFT])
{
e.currentTarget.x -= speed;
e.currentTarget.scaleX = -currentState;
}
}
Poslední aktualizace 11.5.2012
28
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Minimalizace využití CPU
Filmový klip, který lze ovládat klávesnicí
Po klepnutí na tlačítko Odstranit bude filmový klip odebrán ze seznamu zobrazení:
// Show or remove running boy
showBtn.addEventListener (MouseEvent.CLICK,showIt);
removeBtn.addEventListener (MouseEvent.CLICK,removeIt);
function showIt (e:MouseEvent):void
{
addChild (runningBoy);
}
function removeIt(e:MouseEvent):void
{
if (contains(runningBoy)) removeChild(runningBoy);
}
Filmový klip i po odstranění ze seznamu zobrazení odesílá událost Event.ENTER_FRAME. Filmový klip dosud běží, ale
není vykreslován. Chcete-li tuto situaci zpracovat správně, je třeba naslouchat příslušným událostem a odstranit
posluchače událostí, aby nemusel být prováděn kód s velkými nároky na CPU:
Poslední aktualizace 11.5.2012
29
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Minimalizace využití CPU
// Listen to Event.ADDED_TO_STAGE and Event.REMOVED_FROM_STAGE
runningBoy.addEventListener(Event.ADDED_TO_STAGE,activate);
runningBoy.addEventListener(Event.REMOVED_FROM_STAGE,deactivate);
function activate(e:Event):void
{
// Restart everything
e.currentTarget.addEventListener(Event.ENTER_FRAME,handleMovement);
}
function deactivate(e:Event):void
{
// Freeze the running boy - consumes fewer CPU resources when not shown
e.currentTarget.removeEventListener(Event.ENTER_FRAME,handleMovement);
e.currentTarget.stop();
}
Po stisknutí tlačítka Zobrazit je filmový klip znovu spuštěn, opět naslouchá událostem Event.ENTER_FRAME a
ovládání filmového klipu klávesnicí funguje správně.
Poznámka: Pokud je ze seznamu zobrazení odstraněn objekt zobrazení, nastavení jeho odkazu na hodnotu null po
odstranění nezaručuje, že byl tento objekt deaktivován. Pokud není spuštěn nástroj pro uvolnění paměti, objekt bude i
nadále spotřebovávat paměť a prostředky CPU, i když už nebude zobrazen. Chcete-li zajistit, aby objekt spotřebovával
nejmenší možné množství prostředků CPU, je třeba jej při odstraňování ze seznamu zobrazení zcela deaktivovat.
Počínaje aplikací Flash Player 10 a prostředím AIR 1.5 dochází také k následujícímu chování. Objekt zobrazení je
automaticky deaktivován, pokud přehrávací hlava zjistí prázdný snímek, a to i v případě, že nebylo implementováno
žádné chování deaktivace.
Koncept deaktivace je důležitý i při načítání vzdáleného obsahu pomocí třídy Loader. Při používání třídy Loader v
aplikaci Flash Player 9 a prostředí AIR 1.0 bylo nutné ručně deaktivovat obsah nasloucháním události Event.UNLOAD
odeslané objektem LoaderInfo. Každý objekt musel být deaktivován ručně, což nebylo jednoduché. V aplikaci Flash
Player 10 a prostředí AIR 1.5 byla zavedena důležitá nová metoda ve třídě Loader nazvaná unloadAndStop(). Tato
metoda umožňuje odstranit z paměti soubor SWF, automaticky deaktivovat každý objekt v načteném souboru SWF a
vynutit spuštění nástroje pro čištění uvolněné paměti.
V následujícím kódu je soubor SWF načten a pak odstraněn z paměti pomocí metody unload(), která vyžaduje
náročnější zpracování a ruční deaktivaci:
var loader:Loader = new Loader();
loader.load ( new URLRequest ( "content.swf" ) );
addChild ( loader );
stage.addEventListener ( MouseEvent.CLICK, unloadSWF );
function unloadSWF ( e:MouseEvent ):void
{
// Unload the SWF file with no automatic object deactivation
// All deactivation must be processed manually
loader.unload();
}
Osvědčeným postupem je použití metody unloadAndStop(), která provádí deaktivaci nativně a vynucuje spuštění
nástroje pro čištění uvolněné paměti:
Poslední aktualizace 11.5.2012
30
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Minimalizace využití CPU
var loader:Loader = new Loader();
loader.load ( new URLRequest ( "content.swf" ) );
addChild ( loader );
stage.addEventListener ( MouseEvent.CLICK, unloadSWF );
function unloadSWF ( e:MouseEvent ):void
{
// Unload the SWF file with automatic object deactivation
// All deactivation is handled automatically
loader.unloadAndStop();
}
Po volání metody unloadAndStop() proběhnou tyto akce:
• Zastaví se zvuky.
• Budou odstraněny posluchače zaregistrované pro hlavní časovou osu souboru SWF.
• Zastaví se objekty Timer.
• Hardwarová periferní zařízení (jako je kamera a mikrofon) budou uvolněna.
• Zastaví se všechny filmové klipy.
• Odesílání událostí Event.ENTER_FRAME, Event.FRAME_CONSTRUCTED, Event.EXIT_FRAME, Event.ACTIVATE a
Event.DEACTIVATE bude zastaveno.
Události aktivace a deaktivace
Pomocí událostí Event.ACTIVATE a Event.DEACTIVATE lze zjistit nečinnost pozadí a vhodným způsobem aplikaci
optimalizovat.
Dvě události (Event.ACTIVATE a Event.DEACTIVATE) vám mohou pomoci doladit aplikaci tak, aby využívala co
nejmenší počet cyklů CPU. Tyto události vám umožní zjistit, kdy běhové prostředí získá nebo ztratí fokus. Podle toho
může být kód optimalizován tak, aby reagoval na změny kontextu. Následující kód naslouchá oběma událostem a
pokud aplikace ztratí fokus, dynamicky změní kmitočet snímků na nulu. Například animace může ztratit fokus, když
uživatel přepne na jinou kartu nebo umístí danou aplikaci na pozadí:
Poslední aktualizace 11.5.2012
31
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Minimalizace využití CPU
var originalFrameRate:uint = stage.frameRate;
var standbyFrameRate:uint = 0;
stage.addEventListener ( Event.ACTIVATE, onActivate );
stage.addEventListener ( Event.DEACTIVATE, onDeactivate );
function onActivate ( e:Event ):void
{
// restore original frame rate
stage.frameRate = originalFrameRate;
}
function onDeactivate ( e:Event ):void
{
// set frame rate to 0
stage.frameRate = standbyFrameRate;
}
Jakmile aplikace opět získá fokus, obnoví se původní hodnota kmitočtu snímků. Místo dynamické změny kmitočtu
snímků můžete rovněž zvážit jiné možnosti optimalizace, například deaktivace a opětovná aktivace objektů.
Události aktivace a deaktivace vám umožňují, abyste implementovali mechanismus podobný funkci pozastavení a
pokračování, kterou jsou někdy vybaveny mobilní zařízení a netbooky.
Další témata nápovědy
„Kmitočet snímků aplikace“ na stránce 53
„Deaktivace a opětovná aktivace objektů“ na stránce 27
Interakce myši
Zvažte zakázání interakcí myši, je-li to možné.
Při použití interaktivních objektů, jako například MovieClip nebo Sprite, spouští běhové prostředí nativní kód pro
zjištění a zpracování interakcí myši. Zjišťování interakcí myši může mít velké nároky na CPU, jestliže je na obrazovce
zobrazeno mnoho interaktivních objektů, zejména pokud se překrývají. Tomuto náročnému zpracování se lze snadno
vyhnout tak, že zakážete interakce myši u objektů, které interakci myši nevyžadují. Následující kód ukazuje použití
vlastností mouseEnabled a mouseChildren:
Poslední aktualizace 11.5.2012
32
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Minimalizace využití CPU
// Disable any mouse interaction with this InteractiveObject
myInteractiveObject.mouseEnabled = false;
const MAX_NUM:int = 10;
// Create a container for the InteractiveObjects
var container:Sprite = new Sprite();
for ( var i:int = 0; i< MAX_NUM; i++ )
{
// Add InteractiveObject to the container
container.addChild( new Sprite() );
}
// Disable any mouse interaction on all the children
container.mouseChildren = false;
Je-li to možné, zvažte zakázání interakcí myši, čímž lze u aplikace snížit využití prostředků CPU a v důsledku toho i
omezit spotřebu baterií v mobilních zařízeních.
Porovnání časovačů a událostí ENTER_FRAME
V závislosti na tom, zda je obsah animovaný, zvolte buď časovače, nebo události ENTER_FRAME.
V případě neanimovaného obsahu, který běží dlouho, jsou časovače vhodnější než události Event.ENTER_FRAME.
V jazyku ActionScript 3.0 existují dvě možnosti, jak volat funkci v určitých intervalech. Prvním způsobem je použití
události Event.ENTER_FRAME odeslané objekty zobrazení (DisplayObject). Druhý způsob spočívá v použití časovače.
Vývojáři v jazyce ActionScript často používají způsob s použitím události ENTER_FRAME. Událost ENTER_FRAME je
odeslána pro každý snímek. Interval, v němž je funkce volána, se tedy odvíjí od aktuálního kmitočtu snímků. Ke
kmitočtu snímků lze přistupovat pomocí vlastnosti Stage.frameRate. V některých případech však může použití
časovače představovat lepší volbu než použití události ENTER_FRAME. Pokud například nepoužíváte animaci, ale chcete
volat kód v určitých intervalech, může být použití časovače vhodnější.
Časovač se může chovat podobně jako událost ENTER_FRAME, avšak událost může být odeslána nezávisle na kmitočtu
snímků. Toto chování umožňuje výraznou optimalizaci. Vezměme si například aplikaci pro přehrávání videa. V tomto
případě není nutné použít vysoký kmitočet snímků, protože pohyblivé jsou pouze ovládací prvky aplikace.
Poznámka: Kmitočet snímků nemá vliv na video, protože není vloženo do časové osy. Místo toho je video načítáno
dynamicky prostřednictvím progresivního stahování nebo streamování.
V tomto příkladu je kmitočet snímků nastaven na nízkou hodnotu 10 fps. Časovač aktualizuje ovládací prvky s
frekvencí jedné aktualizace za sekundu. Vyšší frekvence aktualizací je možná díky metodě updateAfterEvent(),
která je u objektu TimerEvent k dispozici. Tato metoda vynutí aktualizaci obrazovky pokaždé, když časovač odešle
událost, je-li to třeba. Tuto myšlenku demonstruje následující kód:
Poslední aktualizace 11.5.2012
33
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Minimalizace využití CPU
// Use a low frame rate for the application
stage.frameRate = 10;
// Choose one update per second
var updateInterval:int = 1000;
var myTimer:Timer = new Timer(updateInterval,0);
myTimer.start();
myTimer.addEventListener( TimerEvent.TIMER, updateControls );
function updateControls( e:TimerEvent ):void
{
// Update controls here
// Force the controls to be updated on screen
e.updateAfterEvent();
}
Voláním metody updateAfterEvent() nedojde ke změně kmitočtu snímků. Pouze v běhovém prostředí vynutí
aktualizaci změněného obsahu na obrazovce. Časová osa bude mít stále kmitočet 10 fps. Je třeba si uvědomit, že
časovače a události ENTER_FRAME nejsou zcela přesné u zařízení s nízkým výkonem nebo v případech, kdy funkce
ovladačů událostí obsahují kód, který vyžaduje náročné zpracování. Stejně jako je tomu u kmitočtu snímků souboru
SWF, i frekvence aktualizací časovače se může v některých případech lišit.
Minimalizujte ve své aplikaci počet objektů Timer a registrovaných ovladačů enterFrame.
Každý snímek za běhu odešle událost enterFrame do každého objektu zobrazení ve svém seznamu zobrazení. Ačkoliv
můžete při více objektech zobrazení registrovat posluchače pro každou událost enterFrame, znamená to, že se při
každém snímku provede více kódu. Namísto toho zvažte použití jediného centralizovaného ovladače události
enterFrame, který provede veškerý kód, který se má spustit při každém snímku. Při centralizaci tohoto kódu je
jednodušší spravovat veškerý kód, který se často spouští.
Podobně, pokud používáte objekty Timer, dochází k nadbytečným operacím souvisejícím s vytvářením a odesíláním
událostí z více objektů Timer. Pokud musíte spouštět různé operace v různých intervalech, můžete použít následující
alternativy:
• Použijte minimální počet objektů Timer a seskupte operace podle četnosti jejich provádění..
Použijte například jeden objekt Timer pro časté operace a nastavte spouštění každých 100 milisekund. Použijte
další objekt Timer pro méně časté operace a nastavte spouštění každých 2 000 milisekund.
• Použijte jeden objekt Timer a spouštějte operace při násobcích vlastnosti delay objektu Timer.
Předpokládejme například, že máte nějaké operace, které chcete provádět každých 100 milisekund a ostatní, které
chcete provádět každých 200 milisekund. V tomto případě použijte jeden objekt Timer s hodnotou zpoždění delay
100 milisekund. Do ovladače události timer přidejte podmínku, aby se 200milisekundové operace prováděly každý
druhý cyklus. Tato technika je ukázána v následujícím příkladě:
Poslední aktualizace 11.5.2012
34
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Minimalizace využití CPU
var timer:Timer = new Timer(100);
timer.addEventListener(TimerEvent.Timer, timerHandler);
timer.start();
var offCycle:Boolean = true;
function timerHandler(event:TimerEvent):void
{
// Do things that happen every 100 ms
if (!offCycle)
{
// Do things that happen every 200 ms
}
offCycle = !offCycle;
}
Zastavte objekty Timer, nejsou-li používány.
Pokud ovladač události timer objektu Timer provádí operace pouze za určitých podmínek, volejte metodu stop()
objektu Timer, když není žádná z podmínek true.
V události enterFrame nebo v ovladači objektu Timer minimalizujte počet změn vzhledu objektů zobrazení, které
způsobují překreslení obrazovky.
V každém snímku se ve fázi vykreslování překreslí ta část, která se během tohoto snímku změnila. Pokud je tato oblast
velká, nebo je malá, ale obsahuje velké množství objektů zobrazení nebo složité objekty zobrazení, běh programu
potřebuje více času na vykreslení. Chcete-li vyzkoušet množství potřebného překreslení, použijte při ladění v aplikaci
Flash Player nebo AIR funkci „Zobrazit překreslované oblasti“.
Další informace o zlepšování výkonu pro opakované akce najdete v článku:
• Psaní dobře se chovajících, efektivních aplikací AIR (článek a vzorovou aplikaci napsal Arno Gourdol)
Další témata nápovědy
„Izolování chování“ na stránce 65
Syndrom doplnění
Chcete-li ušetřit výkon CPU, omezte používání doplnění, což šetří prostředky CPU, paměť i životnost baterie.
Návrháři a vývojáři, kteří tvoří obsah Flash určený pro stolní počítače, mají tendenci používat v aplikacích velké
množství doplnění pohybu. Při tvorbě obsahu pro mobilní zařízení s nízkým výkonem se snažte snížit používání
doplnění pohybu na minimum. Když omezíte používání doplnění pohybu, poběží obsah na méně výkonných
zařízeních rychleji.
Poslední aktualizace 11.5.2012
35
36
Kapitola 4: Výkonnost jazyka ActionScript
3.0
Porovnání tříd Vector a Array
Namísto třídy Array používejte pokud možno třídu Vector.
Třída Vector umožňuje rychlejší přístup k zápisu a čtení než třída Array.
Jednoduchý srovnávací test ilustruje výhody třídy Vector oproti třídě Array. Následující kód zobrazuje test výkonnosti
pro třídu Array:
var coordinates:Array = new Array();
var started:Number = getTimer();
for (var i:int = 0; i< 300000; i++)
{
coordinates[i] = Math.random()*1024;
}
trace(getTimer() - started);
// output: 107
Následující kód zobrazuje test výkonnosti pro třídu Vector:
var coordinates:Vector.<Number> = new Vector.<Number>();
var started:Number = getTimer();
for (var i:int = 0; i< 300000; i++)
{
coordinates[i] = Math.random()*1024;
}
trace(getTimer() - started);
// output: 72
Tento příklad kódu lze dále optimalizovat přiřazením určité délky k vektoru a nastavením jeho délky na pevnou
hodnotu:
// Specify a fixed length and initialize its length
var coordinates:Vector.<Number> = new Vector.<Number>(300000, true);
var started:Number = getTimer();
for (var i:int = 0; i< 300000; i++)
{
coordinates[i] = Math.random()*1024;
}
trace(getTimer() - started);
// output: 48
Poslední aktualizace 11.5.2012
37
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost jazyka ActionScript 3.0
Pokud velikost vektoru není předem určena, dojde k jejímu zvětšení, když vektor nemá dostatek místa. Při každém
zvětšení velikosti vektoru je přidělen nový blok paměti. Aktuální obsah vektoru je zkopírován do nového bloku paměti.
Toto přidělení paměti a kopírování dat má navíc negativní vliv na výkon. Určením počáteční velikosti vektoru byl výše
uvedený kód optimalizován pro výkon. Kód však není napsán s ohledem na optimální udržovatelnost. Pro zlepšení
udržovatelnosti kódu je vhodné uložit opakovaně používanou hodnotu do konstanty:
// Store the reused value to maintain code easily
const MAX_NUM:int = 300000;
var coordinates:Vector.<Number> = new Vector.<Number>(MAX_NUM, true);
var started:Number = getTimer();
for (var i:int = 0; i< MAX_NUM; i++)
{
coordinates[i] = Math.random()*1024;
}
trace(getTimer() - started);
// output: 47
Snažte se pokud možno používat rozhraní API objektu Vector, neboť pravděpodobně poběží rychleji.
Kreslicí rozhraní API
Kreslicí rozhraní API používejte ke zrychlení vykonávání kódů.
Aplikace Flash Player 10 a prostředí AIR 1.5 poskytovaly nové kreslicí rozhraní API, které umožňuje dosažení lepšího
výkonu při zpracování kódu. Toto nové rozhraní API nezvyšuje výkon vykreslování, ale značně snižuje počet řádků
kódu, které je nutné napsat. Při menším počtu řádků kódu lze dosáhnout rychlejšího zpracování kódu jazyka
ActionScript.
Nové kreslicí rozhraní API zahrnuje tyto metody:
•
drawPath()
•
drawGraphicsData()
•
drawTriangles()
Poznámka: V tomto tématu se nebudeme zabývat metodou drawTriangles(), která souvisí se zobrazením 3D. Tato
metoda však může zvýšit výkon jazyka ActionScript, protože provádí nativní mapování textur.
Následující kód volá explicitně příslušnou metodu pro každou čáru, která je právě kreslena:
var container:Shape = new Shape();
container.graphics.beginFill(0x442299);
var coords:Vector.<Number> = Vector.<Number>([132, 20, 46, 254, 244, 100, 20, 98, 218, 254]);
container.graphics.moveTo
container.graphics.lineTo
container.graphics.lineTo
container.graphics.lineTo
container.graphics.lineTo
(
(
(
(
(
coords[0],
coords[2],
coords[4],
coords[6],
coords[8],
coords[1]
coords[3]
coords[5]
coords[7]
coords[9]
);
);
);
);
);
addChild( container );
Poslední aktualizace 11.5.2012
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost jazyka ActionScript 3.0
Následující kód běží rychleji než předchozí ukázka, protože zpracovává menší počet řádků. Čím složitější je cesta, tím
větší bude přírůstek výkonu získaný použitím metody drawPath():
var container:Shape = new Shape();
container.graphics.beginFill(0x442299);
var commands:Vector.<int> = Vector.<int>([1,2,2,2,2]);
var coords:Vector.<Number> = Vector.<Number>([132, 20, 46, 254, 244, 100, 20, 98, 218, 254]);
container.graphics.drawPath(commands, coords);
addChild( container );
Metoda drawGraphicsData() přináší podobná zlepšení výkonu.
Zachycování a probublávání událostí
Používejte zachycování a probublávání událostí, abyste omezili ovladače událostí na minimum.
V modelu událostí jazyka ActionScript 3.0 byly nově zavedeny koncepty zachycování událostí a probublávání události.
Probublávání události lze využít k optimalizaci doby provádění kódu ActionScript. Ovladač události můžete místo pro
více objektů registrovat pouze pro jeden objekt, a zvýšit tak výkon.
Představte si například, že vytváříte hru, v níž musí uživatel co nejrychleji klepnout na jablka a tím je zničit. Při
klepnutí na jablko odstraní hra jablko z obrazovky a přičte body k uživatelovu skóre. Pro poslech události
MouseEvent.CLICK odesílané jednotlivými jablky byste možná chtěli napsat následující kód:
const MAX_NUM:int = 10;
var sceneWidth:int = stage.stageWidth;
var sceneHeight:int = stage.stageHeight;
var currentApple:InteractiveObject;
var currentAppleClicked:InteractiveObject;
for ( var i:int = 0; i< MAX_NUM; i++ )
{
currentApple = new Apple();
currentApple.x = Math.random()*sceneWidth;
currentApple.y = Math.random()*sceneHeight;
addChild ( currentApple );
// Listen to the MouseEvent.CLICK event
currentApple.addEventListener ( MouseEvent.CLICK, onAppleClick );
}
function onAppleClick ( e:MouseEvent ):void
{
currentAppleClicked = e.currentTarget as InteractiveObject;
currentAppleClicked.removeEventListener(MouseEvent.CLICK, onAppleClick );
removeChild ( currentAppleClicked );
}
Poslední aktualizace 11.5.2012
38
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost jazyka ActionScript 3.0
Kód volá metodu addEventListener() pro každou instanci Apple. Při klepnutí na jablko dojde k odebrání
příslušného posluchače pomocí metody removeEventListener(). V modelu událostí jazyka ActionScript 3.0 je však
pro některé události k dispozici fáze zachycování a probublávání, díky čemuž jim lze naslouchat z nadřazeného objektu
InteractiveObject. To tedy znamená, že výše uvedený kód je možné optimalizovat a snížit počet volání metod
addEventListener() a removeEventListener(). Následující kód využívá fázi zachycování k poslechu událostí z
nadřazeného objektu:
const MAX_NUM:int = 10;
var sceneWidth:int = stage.stageWidth;
var sceneHeight:int = stage.stageHeight;
var currentApple:InteractiveObject;
var currentAppleClicked:InteractiveObject;
var container:Sprite = new Sprite();
addChild ( container );
// Listen to the MouseEvent.CLICK on the apple's parent
// Passing true as third parameter catches the event during its capture phase
container.addEventListener ( MouseEvent.CLICK, onAppleClick, true );
for ( var i:int = 0; i< MAX_NUM; i++ )
{
currentApple = new Apple();
currentApple.x = Math.random()*sceneWidth;
currentApple.y = Math.random()*sceneHeight;
container.addChild ( currentApple );
}
function onAppleClick ( e:MouseEvent ):void
{
currentAppleClicked = e.target as InteractiveObject;
container.removeChild ( currentAppleClicked );
}
Kód je jednodušší a mnohem lépe optimalizovaný, neboť volá metodu addEventListener() pouze jednou pro
nadřazený kontejner. Posluchače nejsou registrovány k instancím Apple, takže není potřeba je při klepnutí na jablko
odstraňovat. Ovladač onAppleClick() lze dále optimalizovat zastavením šíření události, čímž jí zabráníte pokračovat
v průchodu:
function onAppleClick ( e:MouseEvent ):void
{
e.stopPropagation();
currentAppleClicked = e.target as InteractiveObject;
container.removeChild ( currentAppleClicked );
}
Fázi probublávání lze použít i k zachycení události, jestliže metodě addEventListener() jako třetí parametr předáte
false:
// Listen to the MouseEvent.CLICK on apple's parent
// Passing false as third parameter catches the event during its bubbling phase
container.addEventListener ( MouseEvent.CLICK, onAppleClick, false );
Výchozí hodnota parametru fáze zachycování je false, takže jej můžete vynechat:
container.addEventListener ( MouseEvent.CLICK, onAppleClick );
Poslední aktualizace 11.5.2012
39
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost jazyka ActionScript 3.0
Práce s obrazovými body
Při kreslení obrazových bodů používejte metodu setVector().
Při kreslení obrazových bodů lze některé jednoduché optimalizace provádět pomocí vhodných metod třídy
BitmapData. Obrazové body lze kreslit rychle pomocí metody setVector():
// Image dimensions
var wdth:int = 200;
var hght:int = 200;
var total:int = wdth*hght;
// Pixel colors Vector
var pixels:Vector.<uint> = new Vector.<uint>(total, true);
for ( var i:int = 0; i< total; i++ )
{
// Store the color of each pixel
pixels[i] = Math.random()*0xFFFFFF;
}
// Create a non-transparent BitmapData object
var myImage:BitmapData = new BitmapData ( wdth, hght, false );
var imageContainer:Bitmap = new Bitmap ( myImage );
// Paint the pixels
myImage.setVector ( myImage.rect, pixels );
addChild ( imageContainer );
Pokud pracujete s pomalými metodami, například s metodu setPixel() nebo setPixel32(), použijte ke zrychlení
postupu metody lock() a unlock(). V následujícím kódu jsou ke zvýšení výkonu použity metody lock() a
unlock():
Poslední aktualizace 11.5.2012
40
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost jazyka ActionScript 3.0
var
var
var
var
buffer:BitmapData = new BitmapData(200,200,true,0xFFFFFFFF);
bitmapContainer:Bitmap = new Bitmap(buffer);
positionX:int;
positionY:int;
// Lock update
buffer.lock();
var starting:Number=getTimer();
for (var i:int = 0; i<2000000; i++)
{
// Random positions
positionX = Math.random()*200;
positionY = Math.random()*200;
// 40% transparent pixels
buffer.setPixel32( positionX, positionY, 0x66990000 );
}
// Unlock update
buffer.unlock();
addChild( bitmapContainer );
trace( getTimer () - starting );
// output : 670
Metoda lock() třídy BitmapData uzamkne obraz a znemožní aktualizaci objektů, které na něj odkazují, když dojde
ke změně objektu BitmapData. Pokud například objekt Bitmap odkazuje na objekt BitmapData, můžete objekt
BitmapData uzamknout, změnit a pak odemknout. Objekt Bitmap se změní až po odemčení objektu BitmapData.
Chcete-li zvýšit výkon, použijte tuto metodu společně s metodou unlock() před četnými voláními metod
setPixel() nebo setPixel32 a po nich. Voláním metody lock() a unlock() předejdete zbytečným aktualizacím
obrazovky.
Poznámka: Jestliže jsou zpracovávány obrazové body v bitmapě, která není v seznamu zobrazení (double-buffering,
dvojité ukládání do vyrovnávací paměti), pak použití tohoto způsobu ne vždy vede ke zvýšení výkonu. Pokud objekt
bitmapy neodkazuje na vyrovnávací paměť bitmapy, nedojde při použití metod lock()a unlock() ke zvýšení výkonu.
Aplikace Flash Player zjistí, že neexistuje odkaz na obsah vyrovnávací paměti a bitmapa nebude vykreslena na
obrazovce.
Metody, které iterují přes obrazové body, jako například getPixel(), getPixel32(), setPixel() a setPixel32(),
budou pravděpodobně pomalé, zejména na mobilních zařízeních. Používejte pokud možno metody, jež načtou
všechny obrazové body v jednom volání. K načtení obrazových bodů použijte metodu getVector(), která je rychlejší
než metoda getPixels(). Také pokud možno používejte rozhraní API, která jsou závislá na objektech Vector,
protože pravděpodobně poběží rychleji.
Regulární výrazy
Používejte metody třídy String, například indexOf(), substr() nebo substring() namísto regulárního výrazu
pro základní hledání v řetězci extrahování.
Určité operace, které lze provést pomocí regulárního výrazu, lze rovněž provést pomocí metod třídy String. Chcete-li
například zjistit, zda řetězec obsahuje jiný řetězec, můžete použít buď metodu String.indexOf(), nebo regulární
výraz. Když je však k dispozici třída String, běží rychleji než ekvivalentní regulární výraz a nevyžaduje vytváření
dalšího objektu.
Poslední aktualizace 11.5.2012
41
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost jazyka ActionScript 3.0
Použijte v regulárním výrazu nezachycovací seskupení („(?:xxxx)“) namísto seskupení („(xxxx)“), za účelem
seskupení prvků bez izolování obsahu skupiny do výsledku.
Součásti výrazu se v regulárních výrazech střední složitosti často seskupují. V následujícím vzoru regulárního výrazu
například závorky vytvoří skupinu okolo textu „ab“. Následkem toho kvantifikátor „+“ neplatí jen pro jeden znak, ale
pro celou skupinu:
/(ab)+/
Ve výchozím nastavení je obsah každé skupiny „zachycen“. Můžete získat obsah každé skupiny ve svém vzoru jako
součást výsledku vykonávání regulárního výrazu. Zachycení těchto výsledků skupiny trvá déle a vyžaduje více paměti,
protože objekty jsou vytvářeny tak, aby obsahovaly výsledky skupiny. Jako alternativu můžete použít nezachycovací
syntaxi seskupení vložením otazníku a dvojtečky za levou závorku. Tato syntaxe určuje, že se znaky chovají jako
skupina, ale nejsou zachyceny pro výsledek:
/(?:ab)+/
Použití nezachycovací syntaxe seskupení je rychlejší a využívá méně paměti než použití standardní syntaxe seskupení.
Zvažte použití alternativního regulárního vzoru výrazu, pokud je výkonnost regulárního výrazu slabá.
Někdy je možné použít více než jeden vzor regulárního výrazu k testování nebo rozpoznání stejného vzoru textu.
Z různých důvodů se určité vzory vykonávají rychleji než jiné alternativy. Pokud zjistíte, že nějaký regulární výraz
zpomaluje běh kódu, zvažte použití alternativních vzorů regulárních výrazů dosahujících stejných výsledků.
Vyzkoušejte tyto alternativní vzory a stanovte, který z nich je nejrychlejší.
Různé optimalizace
U objektu TextField používejte namísto operátoru += metodu appendText().
Při práci s vlastností text třídy TextField používejte namísto operátoru += metodu appendText(). Pomocí metody
appendText() lze dosáhnout jistých zlepšení výkonu.
Jako příklad uvádíme kód, který používá operátor +=. Zpracování smyčky trvá 1 120 ms:
addChild ( myTextField );
myTextField.autoSize = TextFieldAutoSize.LEFT;
var started:Number = getTimer();
for (var i:int = 0; i< 1500; i++ )
{
myTextField.text += "ActionScript 3";
}
trace( getTimer() - started );
// output : 1120
V následujícím příkladu je operátor += nahrazen metodou appendText():
Poslední aktualizace 11.5.2012
42
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost jazyka ActionScript 3.0
var myTextField:TextField = new TextField();
addChild ( myTextField );
myTextField.autoSize = TextFieldAutoSize.LEFT;
var started:Number = getTimer();
for (var i:int = 0; i< 1500; i++ )
{
myTextField.appendText ( "ActionScript 3" );
}
trace( getTimer() - started );
// output : 847
Zpracování kódu nyní trvá 847 ms.
Pokud je to možné, aktualizujte textová pole mimo smyčky.
Tento kód lze dále optimalizovat pomocí jednoduché metody. Při aktualizaci textového pole v každé smyčce je
používáno mnoho vnitřních procesů. Použijete-li zřetězený řetězec a přiřadíte ho k textovému poli mimo smyčku,
významně zkrátíte dobu provádění kódu. Zpracování kódu nyní trvá 2 ms:
var myTextField:TextField = new TextField();
addChild ( myTextField );
myTextField.autoSize = TextFieldAutoSize.LEFT;
var started:Number = getTimer();
var content:String = myTextField.text;
for (var i:int = 0; i< 1500; i++ )
{
content += "ActionScript 3";
}
myTextField.text = content;
trace( getTimer() - started );
// output : 2
Při práci s textem HTML je první způsob tak pomalý, že v aplikaci Flash Player může v některých případech vyvolat
výjimku Timeout. K vyvolání výjimky může dojít například v případě, že hostitelský hardware je příliš pomalý.
Poznámka: V prostředí Adobe® AIR® k vyvolání této výjimky nedochází.
var myTextField:TextField = new TextField();
addChild ( myTextField );
myTextField.autoSize = TextFieldAutoSize.LEFT;
var started:Number = getTimer();
for (var i:int = 0; i< 1500; i++ )
{
myTextField.htmlText += "ActionScript <b>2</b>";
}
trace( getTimer() - started );
Přiřadíte-li hodnotu k řetězci mimo smyčku, zpracování kódu potrvá pouze 29 ms:
Poslední aktualizace 11.5.2012
43
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost jazyka ActionScript 3.0
var myTextField:TextField = new TextField();
addChild ( myTextField );
myTextField.autoSize = TextFieldAutoSize.LEFT;
var started:Number = getTimer();
var content:String = myTextField.htmlText;
for (var i:int = 0; i< 1500; i++ )
{
content += "<b>ActionScript<b> 3";
}
myTextField.htmlText = content;
trace ( getTimer() - started );
// output : 29
Poznámka: V aplikaci Flash Player 10.1 a prostředí AIR 2.5 byla třída String vylepšena, takže řetězce využívají méně
paměti.
Pokud je to možné, nepoužívejte operátor hranatá závorka.
Používání operátoru hranatá závorka může zpomalit výkon. Nemusíte jej používat, pokud uložíte odkaz do místní
proměnné. Následující příklad kódu ukazuje neefektivní použití operátoru hranatá závorka:
var lng:int = 5000;
var arraySprite:Vector.<Sprite> = new Vector.<Sprite>(lng, true);
var i:int;
for ( i = 0; i< lng; i++ )
{
arraySprite[i] = new Sprite();
}
var started:Number = getTimer();
for ( i = 0; i< lng; i++ )
{
arraySprite[i].x = Math.random()*stage.stageWidth;
arraySprite[i].y = Math.random()*stage.stageHeight;
arraySprite[i].alpha = Math.random();
arraySprite[i].rotation = Math.random()*360;
}
trace( getTimer() - started );
// output : 16
V následující optimalizované verzi je počet použitých operátorů hranatá závorka snížen:
Poslední aktualizace 11.5.2012
44
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost jazyka ActionScript 3.0
var lng:int = 5000;
var arraySprite:Vector.<Sprite> = new Vector.<Sprite>(lng, true);
var i:int;
for ( i = 0; i< lng; i++ )
{
arraySprite[i] = new Sprite();
}
var started:Number = getTimer();
var currentSprite:Sprite;
for ( i = 0; i< lng; i++ )
{
currentSprite = arraySprite[i];
currentSprite.x = Math.random()*stage.stageWidth;
currentSprite.y = Math.random()*stage.stageHeight;
currentSprite.alpha = Math.random();
currentSprite.rotation = Math.random()*360;
}
trace( getTimer() - started );
// output : 9
Pokud je to možné, používejte řádkový kód, abyste ve svém kódu snížili počet volání funkcí.
Volání funkcí může být nehospodárné. Pokuste se snížit počet volání funkcí přesunutím kódu na řádek. Vložení kódu
na řádek je vhodný způsob optimalizace čistého výkonu. Je ale nutné si uvědomit, že vložený kód může ztížit
opakované používání vašeho kódu a zvětšit soubor SWF. Některá volání funkcí, jako jsou metody třídy Math, lze na
řádek přesunout snadno. Následující kód používá metodu Math.abs() k výpočtu absolutních hodnot:
const MAX_NUM:int = 500000;
var arrayValues:Vector.<Number>=new Vector.<Number>(MAX_NUM,true);
var i:int;
for (i = 0; i< MAX_NUM; i++)
{
arrayValues[i] = Math.random()-Math.random();
}
var started:Number = getTimer();
var currentValue:Number;
for (i = 0; i< MAX_NUM; i++)
{
currentValue = arrayValues[i];
arrayValues[i] = Math.abs ( currentValue );
}
trace( getTimer() - started );
// output : 70
Výpočet, při němž se používá metoda Math.abs(), lze provést ručně a přesunout na řádek:
Poslední aktualizace 11.5.2012
45
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost jazyka ActionScript 3.0
const MAX_NUM:int = 500000;
var arrayValues:Vector.<Number>=new Vector.<Number>(MAX_NUM,true);
var i:int;
for (i = 0; i< MAX_NUM; i++)
{
arrayValues[i] = Math.random()-Math.random();
}
var started:Number = getTimer();
var currentValue:Number;
for (i = 0; i< MAX_NUM; i++)
{
currentValue = arrayValues[i];
arrayValues[i] = currentValue > 0 ? currentValue : -currentValue;
}
trace( getTimer() - started );
// output : 15
Vložením volání funkce na řádek vznikne kód, který je více než čtyřikrát rychlejší. Tento postup je užitečný v mnoha
situacích, pamatujte ale, že může nepříznivě ovlivnit možnost dalšího používání a udržovatelnost.
Poznámka: Velikost kódu má výrazný vliv na celkový běh přehrávače. Pokud aplikace obsahuje velké množství kódu
ActionScript, prostředí virtual machine potřebuje k ověření kódu a kompilaci JIT značné množství času. Vyhledávání
vlastností může být pomalejší kvůli hlubším hierarchiím dědičnosti a také proto, že u vnitřních mezipamětí častěji
dochází k přetížení (thrashing). Chcete-li omezit velikost kódu, nepoužívejte prostředí Adobe® Flex®, knihovnu TLF, ani
jiné knihovny ActionScript třetích stran.
Vyhněte se vyhodnocování příkazů ve smyčce.
Další optimalizace můžete dosáhnout tak, že nebudete vyhodnocovat příkaz ve smyčce. Následující kód provádí iteraci
přes pole, ale není optimalizován, protože délka pole je vyhodnocována pro každou iteraci:
for (var i:int = 0; i< myArray.length; i++)
{
}
Vhodnější postup je hodnotu uložit a opakovaně použít:
var lng:int = myArray.length;
for (var i:int = 0; i< lng; i++)
{
}
U smyček while používejte obrácené pořadí.
Smyčka while v obráceném pořadí je rychlejší než smyčka forward:
Poslední aktualizace 11.5.2012
46
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost jazyka ActionScript 3.0
var i:int = myArray.length;
while (--i > -1)
{
}
Tyto tipy představují několik možností optimalizace kódu v jazyce ActionScript a ukazují, jak může jeden řádek kódu
ovlivnit výkon a paměť. Kód v jazyce ActionScript lze optimalizovat i mnoha dalšími způsoby. Další informace
naleznete prostřednictvím tohoto odkazu: http://www.rozengain.com/blog/2007/05/01/some-actionscript-30optimizations/.
Poslední aktualizace 11.5.2012
47
48
Kapitola 5: Výkonnost vykreslování
Překreslování oblasti
Při budování projektu vždy používejte možnost pro překreslování oblasti.
Z důvodu zlepšeného vykreslování je důležité při budování projektu používat možnost pro překreslování oblasti.
Pomocí této možnosti uvidíte oblasti, které aplikace Flash Player vykresluje a zpracovává. Tuto možnost můžete
aktivovat zvolením příkazu Zobrazit překreslované oblasti v kontextové nabídce ladicí verze aplikace Flash Player.
Poznámka: V prostředí Adobe AIR a ve vydané verzi aplikace Flash Player není možnost Zobrazit překreslované oblasti
k dispozici. (V prostředí Adobe AIR je kontextová nabídka k dispozici pouze v aplikacích pro stolní počítače, avšak
neobsahuje žádné vestavěné nebo standardní položky, jako je možnost Zobrazit překreslované oblasti.)
Následující obrázek znázorňuje tuto možnost zapnutou s jednoduchou animovanou třídou MovieClip na časové ose:
Aktivovaná možnost překreslování oblastí
Tuto možnost můžete aktivovat také v programu a to pomocí metody flash.profiler.showRedrawRegions():
// Enable Show Redraw Regions
// Blue color is used to show redrawn regions
flash.profiler.showRedrawRegions ( true, 0x0000FF );
V aplikacích prostředí Adobe AIR představuje tato metoda jediný způsob, jak aktivovat možnost překreslování oblastí.
Překreslování oblastí lze použít k určení možností pro optimalizaci. Pamatujte si, že ačkoli některé objekty zobrazení
nejsou zobrazeny, stále spotřebovávají cykly CPU, protože jsou stále vykreslovány. Tuto myšlenku znázorňuje
následující obrázek. Černý vektorový tvar zakrývá animovanou běžící postavu. Obrázek znázorňuje, že objekt
zobrazení nebyl odebrán ze seznamu zobrazení a je stále vykreslován. Dochází tak k plýtvání cykly CPU:
Poslední aktualizace 11.5.2012
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
Překreslené oblasti
Chcete-li zlepšit výkon, nastavte vlastnost visible u skryté běžící postavy na hodnotu false nebo ji ze seznamu
zobrazení úplně odeberte. Měli byste rovněž zastavit její časovou osu. Zajistíte tak, že objekt zobrazení bude
deaktivovaný a bude spotřebovávat minimum výkonu CPU.
Nezapomeňte používat možnost pro překreslování oblasti v průběhu celého cyklu vývoje. Budete-li tuto možnost
používat, nebudete na konci projektu překvapeni zbytečnými oblastmi překreslování a oblastmi optimalizace, na které
jste zapomněli.
Další témata nápovědy
„Deaktivace a opětovná aktivace objektů“ na stránce 27
Obsah mimo vymezenou plochu
Vyhněte se umístění obsahu mimo vymezenou plochu. Místo toho v případě potřeby prostě umístěte objekty do
seznamu zobrazení.
Pokud je to možné, neumísťujte grafický obsah mimo vymezenou plochu. Návrháři a vývojáři běžně umísťují prvky
mimo vymezenou plochu, aby mohli datové zdroje během životnosti aplikace opakovaně používat. Tento běžný
postup je znázorněn na následujícím obrázku:
Poslední aktualizace 11.5.2012
49
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
Obsah mimo vymezenou plochu
I když prvky mimo vymezenou plochu nejsou zobrazeny na obrazovce a nejsou vykresleny, nadále existují v seznamu
zobrazení. Běhové prostředí pokračuje ve spouštění interních testů pro tyto prvky za účelem ověření, zda se nadále
nacházejí mimo vymezenou plochu a zda uživatel s nimi neprovádí interakce. Proto se v maximální možné míře
vyhněte umístění objektů mimo vymezenou plochu a místo toho je ze seznamu zobrazení odeberte.
Kvalita filmu
Vykreslování lze zlepšit pomocí vhodného nastavení kvality plochy.
Při vývoji obsahu pro mobilní zařízení s malými obrazovkami, jako jsou telefony, je kvalita obrazu méně důležitá než
při vývoji aplikací pro stolní počítače. Nastavení kvality plochy na vhodnou hodnotu může zvýšit výkon vykreslování.
Poslední aktualizace 11.5.2012
50
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
Pro kvalitu plochy jsou k dispozici tato nastavení:
•
StageQuality.LOW: upřednostňuje rychlost přehrávání před vzhledem a nepoužívá vyhlazování. Toto nastavení
není podporováno v prostředí Adobe AIR pro stolní počítače nebo televize.
•
StageQuality.MEDIUM: aplikuje určitou míru vyhlazení, ale nevyhlazuje bitmapy se změnou velikosti. Toto
nastavení je výchozí hodnotou pro prostředí AIR v mobilních zařízeních, ale není podporováno v prostředí AIR
pro stolní počítače nebo televize.
•
StageQuality.HIGH: (výchozí nastavení pro stolní počítače) upřednostňuje vzhled před rychlostí přehrávání a
vždy používá vyhlazování. Pokud soubor SWF neobsahuje animaci, jsou bitmapy se změnou velikosti vyhlazené;
pokud obsahuje animaci, bitmapy nejsou vyhlazené.
•
StageQuality.BEST: poskytuje nejvyšší kvalitu zobrazení bez ohledu na rychlost přehrávání. Všechny výstupy i
bitmapy se změnou velikosti jsou vždy vyhlazené.
Nastavení StageQuality.MEDIUM obvykle zajišťuje dostatečnou kvalitu pro aplikace v mobilních zařízeních a v
některých případech může přijatelnou kvalitu poskytnout nastavení StageQuality.LOW. Počínaje aplikací Flash
Player 8 lze přesně vykreslit vyhlazený text i při nastavení kvality plochy na hodnotu LOW.
Poznámka: U některých mobilních zařízení, přestože je kvalita nastavena na hodnotu HIGH, se pro lepší výkon v
aplikacích Flash Player používá nastavení MEDIUM. Nastavení kvality na hodnotu HIGH často nepřináší viditelný rozdíl,
protože obrazovky mobilních zařízení mají obvykle větší hodnotu dpi. (Hodnota dpi se může v závislosti na zařízení lišit.)
Na následujícím obrázku je kvalita filmu nastavena na hodnotu MEDIUM a vykreslení textu na hodnotu Vyhladit pro
animaci:
Střední kvalita plochy a vykreslení textu nastavené na hodnotu Vyhladit pro animaci
Toto nastavení kvality plochy nepříznivě ovlivňuje kvalitu textu, protože není použito vhodné nastavení vykreslení
textu.
Běhové prostředí umožňuje nastavit vykreslení textu na možnost Vyhladit pro čitelnost. Toto nastavení zachovává
dokonalou kvalitu vyhlazeného textu bez ohledu na to, jaké nastavení kvality plochy použijete:
Poslední aktualizace 11.5.2012
51
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
Nízká kvalita plochy a vykreslení textu nastavené na hodnotu Vyhladit pro čitelnost
Stejné kvality vykreslení lze docílit nastavením vykreslení textu na hodnotu Bitmapový text (žádné vyhlazení):
Nízká kvalita plochy a vykreslení textu nastavené na hodnotu Bitmapový text (žádné vyhlazení)
Poslední dva příklady ukazují, že textu ve vysoké kvalitě lze dosáhnout bez ohledu na to, jaké nastavení kvality plochy
použijete. Tato funkce je k dispozici počínaje aplikací Flash Player 8 a lze ji použít na mobilních zařízeních.
Nezapomeňte, že aplikace Flash Player 10.1 z důvodu zvýšení výkonu na některých zařízeních automaticky mění
nastavení na StageQuality.MEDIUM.
Prolnutí alfa
Snažte se pokud možno nepoužívat vlastnost alfa.
Nepoužívejte efekty, které při použití vlastnosti alpha vyžadují prolnutí alfa, jako například efekty objevování a
mizení. Pokud objekt zobrazení používá prolnutí alfa, musí běhové prostředí určit konečnou barvu kombinací hodnot
barvy každého překrytého objektu zobrazení a barvy pozadí. Prolnutí alfa tedy může být náročnější na výkon
procesoru než nakreslení neprůhledné barvy. Tyto dodatečné výpočty mohou negativně ovlivnit výkon pomalých
zařízení. Snažte se pokud možno nepoužívat vlastnost alfa.
Poslední aktualizace 11.5.2012
52
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
Další témata nápovědy
„Ukládání bitmapy do mezipaměti“ na stránce 54
„Vykreslování textových objektů“ na stránce 68
Kmitočet snímků aplikace
Obecně používejte nejnižší možný kmitočet snímků k dosažení lepšího výkonu.
Kmitočet snímků aplikace stanovuje, kolik času je k dispozici pro každý cyklus kódu aplikace a vykreslení, tak jak je to
popsáno v části „Základy vykonávání kódu za běhu aplikace“ na stránce 1. Vyšší kmitočet snímků vytváří plynulejší
animaci. Pokud ale animace nebo další vizuální změny neprobíhají, je zbytečné používat vysoký kmitočet snímků.
Vyšší kmitočet snímků spotřebovává více cyklů CPU a energie z baterie než nižší kmitočet.
Následuje několik obecných pokynů ke stanovení vhodného výchozího kmitočtu snímků pro vaši aplikaci:
• Pokud používáte Flex, ponechejte počáteční kmitočet snímků na výchozí hodnotě..
• Pokud vaše aplikace obsahuje animace, je odpovídající kmitočet snímků minimálně 20 snímků za sekundu. Více
než 30 snímků za sekundu je často zbytečné.
• Pokud vaše aplikace neobsahuje animace, kmitočet 12 snímků za sekundu je pravděpodobně vyhovující.
Nejnižší možný kmitočet snímků se může lišit v závislosti na aktuální činnosti aplikace. Další informace najdete
v dalším tipu „Dynamicky měňte kmitočet snímků aplikace“.
Použijte nízký kmitočet snímků, pokud je video jediným dynamickým obsahem vaší aplikace.
Běh programu přehraje obsah videa při svém výchozím kmitočtu snímků bez ohledu na kmitočet snímků aplikace.
Pokud vaše aplikace neobsahuje žádnou animaci nebo rychle se měnící vizuální obsah, použití nižšího kmitočtu
snímků nezhorší požitek uživatelského rozhraní.
Dynamicky měňte kmitočet snímků aplikace.
Výchozí kmitočet snímků aplikace můžete definovat v projektu nebo v nastavení kompilátoru, kmitočet snímků však
není pevně stanovená hodnota. Kmitočet snímků můžete změnit nastavením vlastnosti Stage.frameRate (nebo
v aplikace Flex nastavením vlastnosti WindowedApplication.frameRate).
Měňte kmitočet snímků podle aktuálních potřeb vaší aplikace. Například v době, kdy aplikace neprovádí žádnou
animaci, snižte kmitočet snímků. Když má být spuštěn animovaný přechod, kmitočet snímků zvyšte. Podobně, pokud
vaše aplikace běží na pozadí (poté, co přestane být aktivní), můžete ještě více snížit kmitočet snímků. Uživatel se
pravděpodobně soustředí na jinou aplikaci nebo úlohu.
Následují obecné pokyny, které je vhodné použít jako počáteční bod při stanovování vhodného kmitočtu snímků pro
různé typy aktivit:
• Pokud používáte Flex, ponechejte počáteční kmitočet snímků na výchozí hodnotě..
• Při přehrávání animace nastavte kmitočet snímků minimálně na 20 snímků za sekundu. Více než 30 snímků za
sekundu je často zbytečné.
• Když se žádná animace nepřehrává, kmitočet 12 snímků za sekundu je pravděpodobně vyhovující.
Poslední aktualizace 11.5.2012
53
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
• Načtené video se přehraji při svém výchozím kmitočtu snímků bez ohledu na kmitočet snímků aplikace. Je-li video
jediným pohyblivým obsahem aplikace, kmitočet 12 snímků za sekundu je pravděpodobně vyhovující.
• Když vaše aplikace nemá vstupní fokus, kmitočet 5 snímků za sekundu je pravděpodobně vyhovující.
• Pokud není aplikace AIR viditelná, kmitočet snímků 2 snímky za sekundu nebo méně je pravděpodobně
dostačující. Toto pravidlo platí například pro situaci, kdy aplikace je minimalizována. Platí rovněž pro stolní
zařízení, pokud vlastnost visible nativního okna je nastavena na hodnotu false.
Pro aplikace sestavené v prostředí Flex má třída spark.components. WindowedApplication vestavěnou podporu pro
dynamické změny kmitočtu snímků aplikace. Vlastnost backgroundFrameRate definuje kmitočet snímků, když není
aplikace aktivní. Výchozí hodnota je 1, což změní kmitočet snímků aplikace vybudované na knihovně Spark na 1
snímek za sekundu. Kmitočet snímků na pozadí můžete změnit nastavením vlastnosti backgroundFrameRate. Tuto
vlastnost můžete nastavit i na jinou hodnotu nebo ji můžete nastavit na -1, a tím vypnout automatické omezování
kmitočtu snímků.
Další informace o dynamickém měnění kmitočtu snímků aplikace najdete v následujících článcích:
• Omezování využití CPU v aplikaci Adobe AIR (článek centra Adobe Developer Center a vzorový kód napsal Jonnie
Hallman)
• Psaní dobře se chovajících, efektivních aplikací AIR (článek a vzorovou aplikaci napsal Arno Gourdol)
Grant Skinner vytvořil třídu pro omezení kmitočtu snímků. Tuto třídu můžete používat v aplikacích k automatickému
snižování kmitočtu snímků, když je aplikace na pozadí. Další informace a možnost stažení zdrojového kódu pro třídu
FramerateThrottler naleznete v článku Granta Skinnera „Idle CPU Usage in Adobe AIR and Flash Player“ (v
angličtině) na adrese http://gskinner.com/blog/archives/2009/05/idle_cpu_usage.html.
Adaptivní kmitočet snímků
Při kompilaci souboru SWF jste pro film nastavili určitý kmitočet snímků. V prostředí s omezenými možnostmi s
nízkou frekvencí CPU někdy dochází během přehrávání k poklesu kmitočtu snímků. Běhové prostředí vynechá
vykreslení některých snímků, aby zachovalo přijatelný kmitočet snímků pro uživatele. čímž zabrání poklesu kmitočtu
snímků pod přijatelnou hodnotu.
Poznámka: V tomto případě běhové prostředí nepřeskakuje snímky, pouze vynechává vykreslení obsahu ve snímcích.
Kód je i nadále zpracováván a seznam zobrazení aktualizován, tyto aktualizace se ale nezobrazí na obrazovce.
Neexistuje způsob určení prahové hodnoty fps, z níž by vyplýval počet snímků, které má běhové prostředí přeskočit, když
nemůže zachovat stabilní kmitočet snímků.
Ukládání bitmapy do mezipaměti
Pro složitý vektorový obsah používejte funkci ukládání bitmapy do mezipaměti, je-li to vhodné.
Dobrou optimalizaci lze provést pomocí funkce ukládání bitmapy do mezipaměti. Tato funkce uloží vektorový objekt
do mezipaměti a vnitřně jej vykreslí jako bitmapu, kterou pak použije pro vykreslování. Výsledkem může být
podstatné zvýšení výkonu vykreslování, což však může vyžadovat značné množství paměti. Funkci ukládání bitmapy
do mezipaměti používejte pro složitý vektorový obsah, jako jsou složité přechody nebo text.
Poslední aktualizace 11.5.2012
54
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
Zapnete-li ukládání bitmapy do mezipaměti u animovaného objektu, který obsahuje složité vektorové grafiky
(například text nebo přechody), zvýší se výkon. Pokud je ale ukládání bitmapy do mezipaměti aktivované na objektu
zobrazení, například na filmovém klipu, jehož časová osa je přehrávána, získáte opačný výsledek. U každého snímku
musí běhové prostředí aktualizovat bitmapu uloženou v mezipaměti a poté ji překreslit na obrazovce, což vyžaduje
mnoho cyklů CPU. Funkce ukládání bitmapy do mezipaměti je výhodná pouze v případě, že bitmapu uloženou v
mezipaměti lze jednou vygenerovat a následně používat, aniž by musela být aktualizována.
Pokud zapnete ukládání bitmapy do mezipaměti pro objekt Sprite, je možné objekt přesouvat, aniž by běhové
prostředí muselo bitmapu uloženou v mezipaměti znovu vygenerovat. Změna vlastností x a y objektu nemá za
následek opětovné vygenerování. Při jakémkoli pokusu o otočení objektu nebo změnu jeho velikosti nebo hodnoty alfa
však běhové prostředí musí bitmapu uloženou v mezipaměti znovu vygenerovat, což má negativní vliv na výkon.
Poznámka: U vlastnosti DisplayObject.cacheAsBitmapMatrix, která je k dispozici v prostředí AIR a nástroji pro
tvorbu balíčků pro zařízení iPhone, toto omezení neexistuje. Pomocí vlastnosti cacheAsBitmapMatrix můžete provést
otočení, změnu velikosti, zkosení a změnu hodnoty alfa objektu zobrazení, aniž by bylo nutné bitmapu znovu
vygenerovat.
Bitmapa uložená do mezipaměti může zabrat více paměti než obvyklá instance filmového klipu. Pokud má například
filmový klip na ploše velikost 250 x 250 obrazových bodů, po uložení do mezipaměti využije přibližně 250 kB, zatímco
bez uložení do mezipaměti 1 kB.
V následujícím příkladu se vyskytuje objekt Sprite, který obsahuje obrázek jablka. K symbolu jablka je připojena
následující třída:
package org.bytearray.bitmap
{
import flash.display.Sprite;
import flash.events.Event;
public class Apple extends Sprite
{
private var destinationX:Number;
private var destinationY:Number;
public function Apple ()
{
addEventListener(Event.ADDED_TO_STAGE,activation);
addEventListener(Event.REMOVED_FROM_STAGE,deactivation);
}
private function activation(e:Event):void
{
initPos();
addEventListener (Event.ENTER_FRAME,handleMovement);
}
private function deactivation(e:Event):void
Poslední aktualizace 11.5.2012
55
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
{
removeEventListener(Event.ENTER_FRAME,handleMovement);
}
private function initPos():void
{
destinationX = Math.random()*(stage.stageWidth - (width>>1));
destinationY = Math.random()*(stage.stageHeight - (height>>1));
}
private function handleMovement(e:Event):void
{
x -= (x - destinationX)*.5;
y -= (y - destinationY)*.5;
if (Math.abs(x - destinationX) < 1 && Math.abs(y - destinationY) < 1)
initPos();
}
}
}
Kód využívá namísto třídy MovieClip třídu Sprite, protože pro každé jablko není nutná časová osa. Pro dosažení
nejlepšího výkonu používejte nejmenší možný objekt. Dalším krokem je vytvoření instance uvedené třídy pomocí
následujícího kódu:
Poslední aktualizace 11.5.2012
56
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
import org.bytearray.bitmap.Apple;
stage.addEventListener(MouseEvent.CLICK,createApples);
stage.addEventListener(KeyboardEvent.KEY_DOWN,cacheApples);
const MAX_NUM:int = 100;
var apple:Apple;
var holder:Sprite = new Sprite();
addChild(holder);
function createApples(e:MouseEvent):void
{
for (var i:int = 0; i< MAX_NUM; i++)
{
apple = new Apple();
holder.addChild(apple);
}
}
function cacheApples(e:KeyboardEvent):void
{
if (e.keyCode == 67)
{
var lng:int = holder.numChildren;
for (var i:int = 0; i < lng; i++)
{
apple = holder.getChildAt (i) as Apple;
apple.cacheAsBitmap = Boolean(!apple.cacheAsBitmap);
}
}
}
Když uživatel klepne myší, budou vytvořena jablka, ale nebudou uložena do mezipaměti. Stiskne-li uživatel klávesu C
(kód klávesy 67), vektory jablek budou uloženy do mezipaměti jako bitmapy a zobrazí se na obrazovce. Tato metoda
značně zvyšuje výkon vykreslování, ve stolních počítačích i v mobilních zařízeních, když je procesor pomalý.
Přestože se při použití funkce ukládání bitmapy do mezipaměti zvýší rychlost vykreslování, tato funkce může rychle
spotřebovat velké množství paměti. Po uložení objektu do mezipaměti je jeho povrch zachycen jako průhledná
bitmapa a uložen do paměti, jak znázorňuje následující diagram:
Poslední aktualizace 11.5.2012
57
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
Paměť
Bitmapová verze
Zobrazeno
Vlastnost cacheAsBitmap = true
Objekt a bitmapa jeho povrchu uložená v paměti
Aplikace Flash Player 10.1 a prostředí AIR 2.5 optimalizují využití paměti stejným způsobem, jaký je popsán v části
„Filtry a dynamické odstraňování bitmap z paměti“ na stránce 19. Pokud je objekt zobrazení uložený v mezipaměti
skrytý nebo mimo obrazovku, dojde k uvolnění jeho bitmapy v paměti, když není po určitou dobu používána.
Poznámka: Pokud je vlastnost objektu zobrazení opaqueBackground nastavena na určitou barvu, běhové prostředí
považuje objekt zobrazení za neprůhledný. Při použití s vlastností cacheAsBitmap vytvoří běhové prostředí v paměti
neprůhlednou 32bitovou bitmapu. Kanál alfa bude nastaven na hodnotu 0xFF, což zlepší výkon, protože k vykreslení
bitmapy na obrazovku není zapotřebí průhlednost. Bez prolnutí alfa je vykreslování ještě rychlejší. Pokud je aktuální
barevná hloubka obrazovky omezena na 16 bitů, bude bitmapa v paměti uložena jako 16bitový obraz. Použití vlastnosti
opaqueBackground implicitně neaktivuje ukládání bitmapy do mezipaměti.
Chcete-li ušetřit paměť, použijte vlastnost cacheAsBitmap a aktivujte ji v jednotlivých objektech zobrazení, a nikoli
v kontejneru. Pokud aktivujete funkci ukládání bitmapy do mezipaměti v kontejneru, bude konečná bitmapa v paměti
mnohem větší, neboť se vytvoří průhledná bitmapa s rozměry 211 x 279 obrazových bodů. Obraz využije přibližně
229 kB paměti:
211 obr. bodů
279 obr. bodů
Aktivace funkce ukládání bitmapy do mezipaměti v kontejneru
Poslední aktualizace 11.5.2012
58
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
Při ukládání kontejneru do mezipaměti rovněž riskujete, že při pohybu jakéhokoli jablka ve snímku bude
aktualizována celá bitmapa uložená v paměti. Výsledkem aktivace ukládání bitmapy do mezipaměti v jednotlivých
instancích je uložení šesti povrchů o velikosti 7 kB do mezipaměti, což spotřebuje pouze 42 kB paměti:
Aktivace funkce ukládání bitmapy do mezipaměti v instancích
Při přístupu k jednotlivým instancím jablka prostřednictvím seznamu zobrazení a voláním metody getChildAt()
jsou do objektu Vector ukládány odkazy, které usnadňují přístup:
Poslední aktualizace 11.5.2012
59
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
import org.bytearray.bitmap.Apple;
stage.addEventListener(KeyboardEvent.KEY_DOWN, cacheApples);
const MAX_NUM:int = 200;
var apple:Apple;
var holder:Sprite = new Sprite();
addChild(holder);
var holderVector:Vector.<Apple> = new Vector.<Apple>(MAX_NUM, true);
for (var i:int = 0; i< MAX_NUM; i++)
{
apple = new Apple();
holder.addChild(apple);
holderVector[i] = apple;
}
function cacheApples(e:KeyboardEvent):void
{
if (e.keyCode == 67)
{
var lng:int = holderVector.length
for (var i:int = 0; i < lng; i++)
{
apple = holderVector[i];
apple.cacheAsBitmap = Boolean(!apple.cacheAsBitmap);
}
}
}
Je třeba si uvědomit, že ukládání bitmapy do mezipaměti zvyšuje rychlost vykreslování v případě, že v každém snímku
nedochází ke změně obsahu uloženého v mezipaměti, jeho otočení nebo změně jeho velikosti. U žádných jiných
transformací, než je posun v osách x a y, se ale vykreslení nezrychlí. V takových případech aplikace Flash Player
aktualizuje kopii bitmapy uloženou v mezipaměti při každé transformaci, k níž u objektu zobrazení dojde. Aktualizace
kopie uložené v mezipaměti může vést k vysokému využití CPU, pomalému výkonu a vysoké spotřebě baterie. U
vlastnosti cacheAsBitmapMatrix v prostředí AIR nebo nástroji pro tvorbu balíčků pro zařízení iPhone toto omezení
neexistuje.
Následující kód změní hodnotu alfa v metodě pohybu, čímž se v každém snímku změní krytí jablka:
private function handleMovement(e:Event):void
{
alpha = Math.random();
x -= (x - destinationX)*.5;
y -= (y - destinationY)*.5;
if (Math.abs(x - destinationX) < 1 && Math.abs(y - destinationY) < 1)
initPos();
}
Poslední aktualizace 11.5.2012
60
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
Používání funkce ukládání bitmapy do mezipaměti způsobuje zpomalení výkonu. Po každé změně hodnoty alfa je v
běhovém prostředí vynucena aktualizace bitmapy uložené v mezipaměti.
Filtry jsou závislé na bitmapách, které jsou aktualizovány pokaždé, když se přesune přehrávací hlava filmového klipu
uloženého v mezipaměti. Při použití filtru se vlastnost cacheAsBitmap automaticky nastaví na hodnotu true. Na
následujícím obrázku je animovaný filmový klip:
Animovaný filmový klip
Nepoužívejte filtry na animovaný obsah, protože by mohly způsobit potíže s výkonem. Na následujícím obrázku přidal
grafický návrhář filtr vrženého stínu:
Animovaný filmový klip s filtrem vrženého stínu
To znamená, že pokud probíhá přehrávání časové osy ve filmovém klipu, bitmapa musí být znovu vygenerována.
Bitmapa musí být znovu vygenerována i v případě, že je obsah upraven jakýmkoli způsobem kromě jednoduché
transformace v ose x a y. Každý snímek vynutí v běhovém prostředí překreslení bitmapy, což vyžaduje více prostředků
CPU, snižuje výkon a zvyšuje spotřebu baterie.
Paul Trani v následujících výukových videích uvádí příklady použití aplikace Flash Professional a jazyka ActionScript
k optimalizaci grafiky s použitím bitmap:
• Optimalizace grafiky
• Optimalizace grafiky pomocí jazyka ActionScript
Transformační matice pro bitmapy uložené v mezipaměti v prostředí AIR
Při použití bitmap uložených v mezipaměti v aplikacích prostředí AIR pro mobilní zařízení nastavte vlastnost
cacheAsBitmapMatrix.
Poslední aktualizace 11.5.2012
61
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
V mobilním profilu prostředí AIR můžete k vlastnosti cacheAsBitmapMatrix objektu zobrazení přiřadit objekt
Matrix. Pokud tuto vlastnost nastavíte, můžete pro objekt použít libovolnou dvojrozměrnou transformaci, aniž by bylo
nutné znovu vygenerovat bitmapu uloženou v mezipaměti. Můžete rovněž změnit vlastnost alfa, aniž by bylo nutné
znovu vygenerovat bitmapu uloženou v mezipaměti. Vlastnost cacheAsBitmap musí být rovněž nastavena na
hodnotu true a pro daný objekt nesmí být nastaveny žádné vlastnosti 3D.
Při nastavení vlastnosti cacheAsBitmapMatrix je vygenerována bitmapa uložená do mezipaměti i v případě, že objekt
zobrazení se nachází mimo obrazovku, je v zobrazení skrytý nebo má vlastnost visible nastavenou na hodnotu
false. Při novém nastavení vlastnosti cacheAsBitmapMatrix pomocí objektu matice, jež obsahuje jinou
transformaci, se rovněž znovu vygeneruje bitmapa uložená do mezipaměti.
Transformační matice, kterou použijete u vlastnosti cacheAsBitmapMatrix, bude použita při vykreslení objektu
zobrazení do mezipaměti bitmap. Pokud tedy transformace obsahuje změnu velikosti 2x, bude mít vykreslení bitmapy
oproti vektorovému vykreslení dvojnásobnou velikost. Vykreslovací modul použije pro bitmapu uloženou v
mezipaměti inverzní transformaci, takže konečné zobrazení bude vypadat shodně. Bitmapu uloženou do mezipaměti
můžete zmenšit, čímž se sníží využití paměti, avšak pravděpodobně na úkor věrnosti vykreslení. Můžete rovněž
bitmapu zvětšit, čímž se v některých případech zvýší kvalita vykreslení, avšak zvýší se také využití paměti. Obecně je
však vhodné používat matici identity, což je matice, která nepoužívá žádnou transformaci. Vyhnete se tím změnám
vzhledu, jak ukazuje následující příklad:
displayObject.cacheAsBitMap = true;
displayObject.cacheAsBitmapMatrix = new Matrix();
Po nastavení vlastnosti cacheAsBitmapMatrix můžete provést změnu velikosti, zkosení, otočení a převod objektu,
aniž by bylo nutné bitmapu znovu generovat.
Můžete rovněž změnit hodnotu alfa v rozsahu 0 až 1. Pokud změníte hodnotu alfa prostřednictvím vlastnosti
transform.colorTransform s transformací barev, musí být hodnota alfa použitá v objektu transformace v rozsahu
0 až 255. Změna transformace barev jakýmkoli jiným způsobem znovu vygeneruje bitmapu uloženou do mezipaměti.
Nastavte vlastnost cacheAsBitmapMatrix vždy, když v obsahu vytvořeném pro mobilní zařízení nastavíte vlastnost
cacheAsBitmap na hodnotu true. Mějte však na paměti následující potenciální nevýhodu. Po otočení, změně
velikosti nebo zkosení objektu může konečné vykreslení ve srovnání s normálním vektorovým vykreslením vykazovat
změnu velikosti bitmapy nebo artefakty vyhlazení.
Ruční ukládání bitmapy do mezipaměti
K vytvoření vlastního chování funkce ukládání bitmapy do mezipaměti použijte třídu BitmapData.
V následujícím příkladu je opakovaně použita jedna verze rastrované bitmapy objektu zobrazení a je odkazován stejný
objekt BitmapData. Po změně velikosti jednotlivých objektů zobrazení nebude původní objekt BitmapData v paměti
aktualizován a nebude překreslen. Tento postup šetří prostředky CPU a zrychluje běh aplikací. Při změně velikosti
objektu zobrazení dochází k roztažení bitmapy, která je v něm umístěna.
Zde je aktualizovaná třída BitmapApple:
Poslední aktualizace 11.5.2012
62
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
package org.bytearray.bitmap
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.events.Event;
public class BitmapApple extends Bitmap
{
private var destinationX:Number;
private var destinationY:Number;
public function BitmapApple(buffer:BitmapData)
{
super(buffer);
addEventListener(Event.ADDED_TO_STAGE,activation);
addEventListener(Event.REMOVED_FROM_STAGE,deactivation);
}
private function activation(e:Event):void
{
initPos();
addEventListener(Event.ENTER_FRAME,handleMovement);
}
private function deactivation(e:Event):void
{
removeEventListener(Event.ENTER_FRAME,handleMovement);
}
private function initPos():void
{
destinationX = Math.random()*(stage.stageWidth - (width>>1));
destinationY = Math.random()*(stage.stageHeight - (height>>1));
}
private function handleMovement(e:Event):void
{
alpha = Math.random();
x -= (x - destinationX)*.5;
y -= (y - destinationY)*.5;
if ( Math.abs(x - destinationX) < 1 && Math.abs(y - destinationY) < 1)
initPos();
}
}
}
Hodnota alfa se stále mění v každém snímku. Následující kód předává původní zdrojovou vyrovnávací paměť každé
instanci objektu BitmapApple:
Poslední aktualizace 11.5.2012
63
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
import org.bytearray.bitmap.BitmapApple;
const MAX_NUM:int = 100;
var holder:Sprite = new Sprite();
addChild(holder);
var holderVector:Vector.<BitmapApple> = new Vector.<BitmapApple>(MAX_NUM, true);
var source:AppleSource = new AppleSource();
var bounds:Object = source.getBounds(source);
var mat:Matrix = new Matrix();
mat.translate(-bounds.x,-bounds.y);
var buffer:BitmapData = new BitmapData(source.width+1, source.height+1, true, 0);
buffer.draw(source,mat);
var bitmapApple:BitmapApple;
for (var i:int = 0; i< MAX_NUM; i++)
{
bitmapApple = new BitmapApple(buffer);
holderVector[i] = bitmapApple;
holder.addChild(bitmapApple);
}
Tento postup využívá pouze malé množství paměti, protože v mezipaměti je uložena pouze jedna bitmapa, kterou
všechny instance objektu BitmapApple sdílejí. I přes případné úpravy instance objektu BitmapApple, jako například
nastavení průhlednosti, otočení nebo změna velikosti, nebude původní zdrojová bitmapa nikdy aktualizována.
Pomocí této metody lze zabránit zpomalení výkonu.
Chcete-li získat hladkou konečnou bitmapu, nastavte vlastnost smoothing na hodnotu true:
public function BitmapApple(buffer:BitmapData)
{
super (buffer);
smoothing = true;
addEventListener(Event.ADDED_TO_STAGE, activation);
addEventListener(Event.REMOVED_FROM_STAGE, deactivation);
}
Výkon lze zvýšit i změnou nastavení kvality plochy. Před rastrováním nastavte kvalitu plochy na hodnotu HIGH, pak ji
přepněte na hodnotu LOW:
Poslední aktualizace 11.5.2012
64
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
import org.bytearray.bitmap.BitmapApple;
const MAX_NUM:int = 100;
var holder:Sprite = new Sprite();
addChild ( holder );
var holderVector:Vector.<BitmapApple> = new Vector.<BitmapApple>(MAX_NUM, true);
var source:AppleSource = new AppleSource();
var bounds:Object = source.getBounds ( source );
var mat:Matrix = new Matrix();
mat.translate ( -bounds.x, -bounds.y );
var buffer:BitmapData = new BitmapData ( source.width+1, source.height+1, true, 0 );
stage.quality = StageQuality.HIGH;
buffer.draw ( source, mat );
stage.quality = StageQuality.LOW;
var bitmapApple:BitmapApple;
for (var i:int = 0; i< MAX_NUM; i++ )
{
bitmapApple = new BitmapApple( buffer );
holderVector[i] = bitmapApple;
holder.addChild ( bitmapApple );
}
Přepnutí nastavení kvality plochy před překreslením vektoru na bitmapu a po něm představuje účinný způsob, jak na
obrazovce vytvořit vyhlazený obsah. Tento postup funguje bez ohledu na konečné nastavení kvality plochy. Můžete
tak například dosáhnout vyhlazené bitmapy s vyhlazeným textem, i když je kvalita plochy nastavena na hodnotu LOW.
Tuto metodu nelze použít s vlastností cacheAsBitmap. V takovém případě dojde při nastavení kvality plochy na
hodnotu LOW k aktualizaci kvality vektoru a v důsledku toho k aktualizaci povrchů v paměti a k aktualizaci konečné
kvality.
Izolování chování
Snažte se události jako například událost Event.ENTER_FRAME pokud možno izolovat do jediného ovladače.
Kód lze dále optimalizovat izolováním události Event.ENTER_FRAME ve třídě Apple do jediného ovladače. Takovýto
postup šetří prostředky CPU. Tento odlišný přístup je znázorněn v následujícím příkladu, kde již chování pohybu
nezpracovává třída BitmapApple:
Poslední aktualizace 11.5.2012
65
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
package org.bytearray.bitmap
{
import flash.display.Bitmap;
import flash.display.BitmapData;
public class BitmapApple extends Bitmap
{
private var destinationX:Number;
private var destinationY:Number;
public function BitmapApple(buffer:BitmapData)
{
super (buffer);
smoothing = true;
}
}
Následující kód vytvoří instance jablek a zpracovává jejich pohyb v jediném ovladači:
import org.bytearray.bitmap.BitmapApple;
const MAX_NUM:int = 100;
var holder:Sprite = new Sprite();
addChild(holder);
var holderVector:Vector.<BitmapApple> = new Vector.<BitmapApple>(MAX_NUM, true);
var source:AppleSource = new AppleSource();
var bounds:Object = source.getBounds(source);
var mat:Matrix = new Matrix();
mat.translate(-bounds.x,-bounds.y);
stage.quality = StageQuality.BEST;
var buffer:BitmapData = new BitmapData(source.width+1,source.height+1, true,0);
buffer.draw(source,mat);
stage.quality = StageQuality.LOW;
var bitmapApple:BitmapApple;
for (var i:int = 0; i< MAX_NUM; i++)
{
bitmapApple = new BitmapApple(buffer);
bitmapApple.destinationX = Math.random()*stage.stageWidth;
bitmapApple.destinationY = Math.random()*stage.stageHeight;
holderVector[i] = bitmapApple;
holder.addChild(bitmapApple);
}
stage.addEventListener(Event.ENTER_FRAME,onFrame);
Poslední aktualizace 11.5.2012
66
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
var lng:int = holderVector.length
function onFrame(e:Event):void
{
for (var i:int = 0; i < lng; i++)
{
bitmapApple = holderVector[i];
bitmapApple.alpha = Math.random();
bitmapApple.x -= (bitmapApple.x - bitmapApple.destinationX) *.5;
bitmapApple.y -= (bitmapApple.y - bitmapApple.destinationY) *.5;
if (Math.abs(bitmapApple.x - bitmapApple.destinationX ) < 1 &&
Math.abs(bitmapApple.y - bitmapApple.destinationY ) < 1)
{
bitmapApple.destinationX = Math.random()*stage.stageWidth;
bitmapApple.destinationY = Math.random()*stage.stageHeight;
}
}
}
Výsledkem je jediná událost Event.ENTER_FRAME, která zpracovává pohyb, a nikoli 200 ovladačů, které přesouvají
jednotlivá jablka. Celou animaci lze snadno pozastavit, což může být ve hře užitečné.
Následující ovladač může být například používán jednoduchou hrou:
stage.addEventListener(Event.ENTER_FRAME, updateGame);
function updateGame (e:Event):void
{
gameEngine.update();
}
Dalším krokem je zajištění interakce jablek s myší nebo klávesnicí, což vyžaduje úpravy třídy BitmapApple.
package org.bytearray.bitmap
{
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Sprite;
public class BitmapApple extends Sprite
{
public var destinationX:Number;
public var destinationY:Number;
private var container:Sprite;
private var containerBitmap:Bitmap;
public function BitmapApple(buffer:BitmapData)
{
container = new Sprite();
containerBitmap = new Bitmap(buffer);
containerBitmap.smoothing = true;
container.addChild(containerBitmap);
addChild(container);
}
}
Poslední aktualizace 11.5.2012
67
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
Výsledkem jsou instance objektu BitmapApple, které jsou interaktivní podobně jako tradiční objekty Sprite. Tyto
instance jsou však propojeny s jedinou bitmapou, která není převzorkována, když dojde k transformaci objektů
zobrazení.
Vykreslování textových objektů
Chcete-li zvýšit výkon vykreslení textu, použijte funkci ukládání bitmapy do mezipaměti a vlastnost
opaqueBackground.
Textový modul Flash nabízí značné možnosti optimalizace. K zobrazení jednoho řádku textu je však zapotřebí mnoho
tříd. Proto vyžaduje vytvoření upravitelného textového pole pomocí třídy TextLine značné množství paměti a mnoho
řádků kódu jazyka ActionScript. Třída TextLine je nejvhodnější pro statický a neupravitelný text, u něhož vykresluje
rychleji a vyžaduje méně paměti.
Funkce ukládání bitmapy do mezipaměti dovoluje uložit do mezipaměti vektorový obsah jako bitmapy, aby se zvýšil
výkon vykreslování. Tato funkce je užitečná pro složitý vektorový obsah a také v případě použití s textovým obsahem,
který je nutné kvůli vykreslení zpracovat.
Následující příklad znázorňuje, jak lze funkci ukládání bitmapy do mezipaměti a vlastnost opaqueBackground použít
ke zvýšení výkonu vykreslování. Následující obrázek znázorňuje typickou úvodní obrazovku, kterou lze zobrazit, když
uživatel čeká na načtení položky:
Úvodní obrazovka
Následující obrázek znázorňuje nabíhání použité na objekt TextField programově. Text nabíhá pomalu od horního
okraje scény do jejího středu:
Poslední aktualizace 11.5.2012
68
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
Nabíhání textu
Nabíhání lze vytvořit pomocí následujícího kódu. V proměnné preloader je uložen aktuální cílový objekt, díky
čemuž je omezeno vyhledávání vlastností, které může snižovat výkon:
wait_mc.addEventListener( Event.ENTER_FRAME, movePosition );
var destX:Number=stage.stageWidth/2;
var destY:Number=stage.stageHeight/2;
var preloader:DisplayObject;
function movePosition( e:Event ):void
{
preloader = e.currentTarget as DisplayObject;
preloader.x -= ( preloader.x - destX ) * .1;
preloader.y -= ( preloader.y - destY ) * .1;
if (Math.abs(preloader.y-destY)<1)
preloader.removeEventListener( Event.ENTER_FRAME, movePosition );
}
Poslední aktualizace 11.5.2012
69
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
Pokud byste chtěli omezit počet volání funkce a dále optimalizovat výkon, bylo by zde možné přesunout funkci
Math.abs() na řádek. Osvědčený postup je použít pro vlastnosti destX a destY typ int, abyste získali hodnoty s
pevnou desetinnou čárkou. Pomocí typu int docílíte bezchybného přitahování obrazových bodů, aniž by bylo nutné
zaokrouhlovat hodnoty ručně pomocí pomalých metod, jako je Math.ceil() nebo Math.round(). Tento kód
souřadnice nezaokrouhluje na typ int, protože pokud jsou hodnoty neustále zaokrouhlovány, pohyb objektu není
plynulý. Pohyby objektu mohou být trhavé, protože souřadnice jsou v každém snímku přitahovány k nejbližším
zaokrouhleným celým číslům. Tento postup však může být užitečný při nastavování konečné polohy objektu
zobrazení. Nepoužívejte následující kód:
// Do not use this code
var destX:Number = Math.round ( stage.stageWidth / 2 );
var destY:Number = Math.round ( stage.stageHeight / 2);
Mnohem rychlejší je tento kód:
var destX:int = stage.stageWidth / 2;
var destY:int = stage.stageHeight / 2;
Předchozí kód lze dále optimalizovat rozdělením hodnot pomocí operátorů bitového posunu:
var destX:int = stage.stageWidth >> 1;
var destY:int = stage.stageHeight >> 1;
Funkce ukládání bitmapy do mezipaměti usnadňuje v běhovém prostředí vykreslování objektů pomocí dynamických
bitmap. V tomto příkladu je filmový klip obsahující objekt TextField uložen do mezipaměti:
wait_mc.cacheAsBitmap = true;
Další možností zvýšení výkonu je odstranění průhlednosti alfa. Průhlednost alfa způsobuje další zatížení běhového
prostředí při kreslení průhledných bitmapových obrazů, jak tomu bylo v předchozím kódu. Můžete ji obejít pomocí
vlastnosti opaqueBackground a určením barvy jako pozadí.
Při použití vlastnosti opaqueBackground využívá bitmapový povrch vytvořený v paměti stále 32 bitů. Posun alfa je
však nastaven na hodnotu 255 a není použita průhlednost. V důsledku toho vlastnost opaqueBackground nesníží
využití paměti, ale zvýší výkon vykreslování, bude-li použita funkce ukládání bitmapy do mezipaměti. Následující kód
obsahuje všechny uvedené optimalizace:
wait_mc.addEventListener( Event.ENTER_FRAME, movePosition );
wait_mc.cacheAsBitmap = true;
// Set the background to the color of the scene background
wait_mc.opaqueBackground = 0x8AD6FD;
var destX:int = stage.stageWidth >> 1;
var destY:int = stage.stageHeight >> 1;
var preloader:DisplayObject;
function movePosition ( e:Event ):void
{
preloader = e.currentTarget as DisplayObject;
preloader.x -= ( preloader.x - destX ) * .1;
preloader.y -= ( preloader.y - destY ) * .1;
if ( Math.abs ( preloader.y - destY ) < 1 )
e.currentTarget.removeEventListener ( Event.ENTER_FRAME, movePosition );
}
Poslední aktualizace 11.5.2012
70
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
Animace je nyní optimalizovaná a ukládání bitmapy do mezipaměti bylo optimalizováno odstraněním průhlednosti.
V mobilních zařízeních zvažte možnost přepínání kvality plochy na hodnotu LOW a HIGH v průběhu různých stavů
animace a současně použití funkce ukládání bitmapy do mezipaměti:
wait_mc.addEventListener( Event.ENTER_FRAME, movePosition );
wait_mc.cacheAsBitmap = true;
wait_mc.opaqueBackground = 0x8AD6FD;
// Switch to low quality
stage.quality = StageQuality.LOW;
var destX:int = stage.stageWidth>>1;
var destY:int = stage.stageHeight>>1;
var preloader:DisplayObject;
function movePosition( e:Event ):void
{
preloader = e.currentTarget as DisplayObject;
preloader.x -= ( preloader.x - destX ) * .1;
preloader.y -= ( preloader.y - destY ) * .1;
if (Math.abs(e.currentTarget.y-destY)<1)
{
// Switch back to high quality
stage.quality = StageQuality.HIGH;
preloader.removeEventListener( Event.ENTER_FRAME, movePosition );
}
}
Avšak v tomto případě změna kvality plochy vynutí v běhovém prostředí nové vytvoření povrchu bitmapy objektu
TextField, aby odpovídal aktuální kvalitě plochy. Proto je nejvhodnější, pokud používáte funkci ukládání bitmapy do
mezipaměti, kvalitu plochy neměnit.
Zde bylo možné použít ruční způsob ukládání bitmapy do mezipaměti. Za účelem simulace vlastnosti
opaqueBackground lze filmový klip kreslit na neprůhledný objekt BitmapData, což v běhovém prostředí nevynutí
nové vytvoření povrchu bitmapy.
Tato metoda je vhodná pro obsah, který se v průběhu času nemění. Pokud se ale obsah textového pole může měnit,
zvažte použití jiné strategie. Představte si například textové pole nepřetržitě aktualizované procentuální hodnotou,
která představuje načtenou část aplikace. Pokud bylo textové pole nebo objekt, který je obsahuje, uloženo do
mezipaměti jako bitmapa, jeho povrch musí být vytvořen po každé změně obsahu. Ruční ukládání bitmapy do
mezipaměti nelze v tomto případě použít, protože se obsah objektu zobrazení neustále mění. Kvůli těmto neustálým
změnám byste museli bitmapu uloženou v mezipaměti aktualizovat ručním voláním metody BitmapData.draw().
Pamatujte, že počínaje aplikací Flash Player 8 (a prostředím AIR 1.0) bude textové pole s vykreslením nastaveným na
hodnotu Vyhladit pro čitelnost i nadále bezchybně vyhlazeno bez ohledu na hodnotu kvality plochy. Tato metoda
spotřebuje méně paměti, ale vyžaduje více prostředků CPU pro zpracování a vykresluje poněkud pomaleji než funkce
ukládání bitmapy do mezipaměti.
Tento postup je použit v následujícím kódu:
Poslední aktualizace 11.5.2012
71
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
wait_mc.addEventListener( Event.ENTER_FRAME, movePosition );
// Switch to low quality
stage.quality = StageQuality.LOW;
var destX:int = stage.stageWidth >> 1;
var destY:int = stage.stageHeight >> 1;
var preloader:DisplayObject;
function movePosition ( e:Event ):void
{
preloader = e.currentTarget as DisplayObject;
preloader.x -= ( preloader.x - destX ) * .1;
preloader.y -= ( preloader.y - destY ) * .1;
if ( Math.abs ( preloader.y - destY ) < 1 )
{
// Switch back to high quality
stage.quality = StageQuality.HIGH;
preloader.removeEventListener ( Event.ENTER_FRAME, movePosition );
}
}
Používání této volby (Vyhladit pro čitelnost) není vhodné pro text v pohybu. Při změnách velikosti textu tato volba
způsobuje, že má text snahu zachovat zarovnání, čímž dochází k efektu posunutí. Pokud se však obsah objektu
zobrazení neustále mění a potřebujete text se změněnou velikostí, můžete výkon v aplikacích pro mobilní zařízení
zvýšit nastavením kvality na hodnotu LOW. Po dokončení pohybu přepněte kvalitu zpět na hodnotu HIGH.
GPU
Vykreslování GPU v aplikacích Flash Player
Jednou z důležitých nových funkcí aplikace Flash Player 10.1 je možnost použití GPU k vykreslení grafického obsahu
na mobilních zařízeních. Dříve byly grafiky vykreslovány pouze prostřednictvím CPU. Použití GPU vede k
optimalizaci vykreslování filtrů, bitmap, videa a textu. Je třeba si uvědomit, že vykreslování GPU není vždy tak přesné
jako softwarové vykreslování. Při použití hardwarového vykreslování může mít obsah hrubší vzhled. V aplikaci Flash
Player 10.1 rovněž existuje omezení, které může zabránit vykreslování některých efektů Pixel Bender na obrazovce.
Tyto efekty mohou být při použití hardwarové akcelerace vykreslovány jako černý čtverec.
Aplikace Flash Player 10 sice disponovala funkcí akcelerace GPU, ale GPU nebylo používáno k výpočtům grafik.
Sloužilo pouze k odeslání všech grafik na obrazovku. V aplikaci Flash Player 10.1 se GPU používá rovněž k výpočtům
grafik, díky čemuž lze výrazně zrychlit vykreslování. Snižuje se tím také zatížení CPU, což je užitečné u zařízení s
omezenými prostředky, jako jsou mobilní zařízení.
Režim GPU je při spouštění obsahu v mobilních zařízeních automaticky nastaven tak, aby bylo dosaženo nejlepšího
možného výkonu. Přestože k povolení vykreslování GPU již není nutné nastavit parametr wmode na hodnotu gpu,
nastavením parametru wmode na hodnotu opaque nebo transparent akceleraci GPU zakážete.
Poznámka: Aplikace Flash Player ve stolních počítačích nadále používá CPU pro softwarové vykreslování. Softwarové
vykreslování je používáno z toho důvodu, že ovladače pro stolní počítače se značně liší a mohou zdůraznit rozdíly ve
vykreslování. Vykreslování se rovněž může lišit u stolních počítačů a některých mobilních zařízení.
Poslední aktualizace 11.5.2012
72
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
Vykreslování GPU v aplikacích prostředí AIR pro mobilní zařízení
Zapněte hardwarovou akceleraci grafiky v aplikaci prostředí AIR tím, že do deskriptoru aplikace zahrnete kód
<renderMode>gpu</renderMode>. Režimy vykreslování nelze měnit za běhu. Ve stolních počítačích je nastavení
renderMode ignorováno. Akcelerace grafiky GPU není nyní podporována.
Omezení režimu vykreslování GPU
Při použití režimu vykreslování GPU v prostředí AIR 2.5 existují následující omezení:
• Pokud GPU nemůže objekt vykreslit, nebude objekt vůbec zobrazen. Není k dispozici záloha v podobě vykreslování CPU.
• Nejsou podporovány následující režimy prolnutí: Vrstva, Alfa, Vymazat, Překrýt, Tvrdé světlo, Zesvětlit a Ztmavit.
• Nejsou podporovány filtry.
• Není podporován nástroj PixelBender.
• Mnoho jednotek GPU má maximální velikost textury 1 024 x 1 024. V jazyce ActionScript to znamená maximální
konečnou vykreslenou velikost objektu zobrazení po provedení všech transformací.
• Společnost Adobe nedoporučuje používání režimu vykreslování GPU v aplikacích prostředí AIR, jež přehrávají
video.
• V režimu vykreslování GPU nejsou při otevření virtuální klávesnice textová pole vždy přesunuta do viditelného
umístění. Chcete-li zajistit, aby při zadávání textu uživatelem bylo vaše textové pole viditelné, proveďte jeden z
následujících úkonů. Umístěte textové pole do horní poloviny obrazovky, nebo je přesuňte do horní poloviny
obrazovky, když získá fokus.
• Režim vykreslování GPU je zakázán pro některá zařízení, ve kterých nefunguje spolehlivě. Nejnovější informace
naleznete v poznámkách k verzi pro vývojáře prostředí AIR.
Doporučené postupy pro režim vykreslování GPU
Dodržování následujících pravidel může vykreslování GPU urychlit:
• Omezte počet viditelných položek na ploše. Vykreslení položky a její sloučení s okolními položkami určitou dobu
trvá. Pokud již dále objekt zobrazení nechcete zobrazovat, nastavte jeho vlastnost visible na hodnotu false.
Nepřesunujte jej pouze mimo vymezenou plochu, neskrývejte jej za jiný objekt, ani nenastavujte jeho vlastnost
alpha na hodnotu 0. Pokud již dále objekt zobrazení vůbec nepotřebujete, odeberte jej z plochy pomocí metody
removeChild().
• Místo vytváření a rušení objektů spíše používejte objekty opakovaně.
• Velikosti vytvořených bitmap by se měly těsně přibližovat 2n x 2m bitů. Není třeba, aby rozměry byly přesné
mocniny dvou, měly by se ale mocninám dvou blížit a nepřekračovat je. Například obraz o rozměrech 31 x 15 obr.
bodů bude vykreslován rychleji než obraz o rozměrech 33 x 17 obr. bodů. (Hodnoty 31 a 15 jsou o něco menší než
mocniny dvou, což jsou hodnoty 32 a 16.)
• Je-li to možné, nastavte při volání metody Graphic.beginBitmapFill() parametr repeat na hodnotu false.
• Nepřekreslujte. Používejte jako pozadí barvu pozadí. Neumísťujte do vrstev velké objekty jeden na druhý. Každý
vykreslený obrazový bod ubírá určitý výpočetní výkon.
• Snažte se nepoužívat dlouhé a tenké špičaté tvary, okraje protínající samy sebe nebo velké množství jemných detailů
na okrajích. Vykreslení těchto tvarů trvá delší dobu než u objektů zobrazení s hladkými okraji.
• Omezte velikost objektů zobrazení.
• Nastavte vlastnosti cacheAsBitMap a cacheAsBitmapMatrix pro objekty zobrazení, jejichž grafiky nejsou často
aktualizovány.
Poslední aktualizace 11.5.2012
73
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
• Nepoužívejte k vytváření grafik kreslicí rozhraní API jazyka ActionScript (třídu Graphics). Je-li to možné,
vytvářejte tyto objekty raději staticky v době vytváření.
• Před importem nastavte datové zdroje bitmap na konečnou velikost.
Režim vykreslování GPU v prostředí AIR 2.0.3 pro mobilní zařízení
Vykreslování GPU v mobilních aplikacích prostředí AIR, jež jsou vytvořeny pomocí nástroje pro tvorbu balíčků pro
zařízení iPhone, přináší více omezení. GPU je efektivní pouze pro bitmapy, plné tvary a objekty zobrazení, které mají
nastavenou vlastnost cacheAsBitmap. U objektů s nastavenou vlastností cacheAsBitmap a cacheAsBitmapMatrix
může GPU efektivně vykreslovat i objekty, u nichž dochází k otočení nebo ke změně velikosti. GPU je současně
používáno pro další objekty zobrazení, což má obvykle za následek nižší výkon vykreslování.
Tipy pro optimalizaci výkonu vykreslování GPU
Vykreslování GPU sice může výrazně zvýšit výkon obsahu SWF, avšak důležitou roli hraje návrh obsahu.
Upozorňujeme, že nastavení, jež dříve dobře fungovalo při softwarovém vykreslování, někdy nemusí dobře fungovat
při vykreslování GPU. Následující tipy vám pomohou dosáhnout dobrý výkon vykreslování GPU, aniž by byl
negativně ovlivněn výkon softwarového vykreslování.
Poznámka: Mobilní zařízení, jež podporují hardwarové vykreslování, často přistupují k obsahu SWF z webu. K zajištění
nejlepší kvality na všech obrazovkách je proto vhodné, aby tyto tipy byly brány v úvahu při vytváření jakéhokoli obsahu SWF.
• V parametrech HTML tagu embed nepoužívejte režimy wmode=transparent a wmode=opaque. Tyto režimy
mohou způsobit snížení výkonu. Tyto režimy mohou mít při softwarovém i hardwarovém vykreslování za následek
rovněž drobné ztráty v synchronizaci zvuku a videa. Navíc při použití těchto režimů řada platforem nepodporuje
vykreslování GPU, takže výkon se významně zhorší.
• Používejte pouze režimy prolnutí Normální a Alfa. Nepoužívejte jiné režimy prolnutí, zejména režim prolnutí
Vrstva. Při vykreslování prostřednictvím GPU nemusejí být všechny režimy reprodukovány věrně.
• Při vykreslování vektorové grafiky pomocí GPU je příslušná grafika před vykreslením rozložena na mřížku
tvořenou malými trojúhelníky. Tento proces se nazývá vytvoření mozaiky. Vytvoření mozaiky má za následek
drobné snížení výkonu, jež se však s nárůstem složitosti tvarů zvětšuje. Chcete-li minimalizovat dopad na výkon,
nepoužívejte morfované tvary, pro něž vykreslování GPU vytváří mozaiku na každém snímku.
• Nepoužívejte křivky, jež se samy protínají, velmi tenké zakřivené oblasti (například tenký půlměsíc) a
komplikované detaily u okrajů tvaru. Při vytváření trojúhelníkové mřížky mozaiky jsou tyto tvary pro GPU složité.
Pro pochopení si představte dva vektory: čtverec o velikosti 500 × 500 a půlměsíc o velikosti 100 × 10. GPU snadno
vykreslí velký čtverec, protože se jedná pouze o dva trojúhelníky. Popis křivky půlměsíce však vyžaduje mnoho
trojúhelníků. Vykreslení tohoto tvaru je tedy složitější, i když tento tvar obsahuje méně obrazových bodů.
• Nepoužívejte velké změny velikosti, protože takové změny rovněž mohou způsobit, že GPU pro grafiku opětovně
vytváří mozaiku.
• Nepoužívejte překreslování, pokud je to možné. Překreslování je vrstvení více grafických prvků tak, že se navzájem
zakrývají. Při softwarovém vykreslování je každý obrazový bod vykreslen pouze jednou. Proto bez ohledu na počet
grafických prvků, které se na místě obrazového bodu navzájem zakrývají, není při softwarovém vykreslování výkon
aplikace negativně ovlivněn. Oproti tomu při hardwarovém vykreslování je každý obrazový bod vykreslen bez
ohledu na to, zda danou oblast zakrývají jiné prvky. Pokud se dva obdélníky vzájemně překrývají, je překrytá oblast
při hardwarovém vykreslování vykreslena dvakrát, zatímco při softwarovém vykreslování je tato oblast vykreslena
pouze jednou.
Ve stolních počítačích, jež používají softwarové vykreslování, obvykle dopad překreslování na výkon není znát. V
zařízeních používajících vykreslování GPU však velké množství překrývajících se tvarů může snižovat výkon.
Doporučeným postupem je odebrání objektů ze seznamu zobrazení, nikoli jejich skrytí.
Poslední aktualizace 11.5.2012
74
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
• Jako pozadí nepoužívejte velký obdélník s výplní. Místo toho nastavte barvu pozadí plochy.
• Nepoužívejte výchozí režim výplně bitmapy při opakování bitmap, pokud je to možné. Místo toho pro dosažení
lepšího výkonu používejte režim přichycení bitmapy.
Asynchronní operace
Tam, kde je to možné, dávejte přednost asynchronním verzím operací před synchronními.
Synchronní operace se spouští jakmile jim to váš kód určí a potom čeká na dokončení, než se posune dále. Následkem
toho běží ve smyčce snímku ve fázi kódu. Pokud synchronní operace trvají příliš dlouho, protáhnou délku smyčky
snímku, což může případně způsobit zamrznutí nebo sekání zobrazení.
Když kód vykoná asynchronní operaci, nemusí se nutně okamžitě spuštěna. Váš kód a kód další aplikace v aktuálním
vlákně vykonávání budou pokračovat ve vykonávání. Běh programu potom danou operaci provede, jakmile to bude
možné, přičemž se pokouší zabránit problémům s vykreslením. V některých případech vykonávání probíhá na pozadí
a nespouští se za běhu smyčky snímku. Nakonec, když je operace dokončena, běh programu odešle událost. Váš
program může této události naslouchat, aby mohl provést další práci.
Asynchronní operace jsou naplánovány a rozděleny, aby nedocházelo k problémům s vykreslením. Proto je mnohem
jednodušší mít reagující aplikací, která využívá asynchronní verze operací. Další informace najdete v části „Vnímaný
výkon versus skutečný výkon“ na stránce 2.
Při asynchronním běhu operací ale dochází k určitým nadbytečným operacím. Skutečná doba provádění může být u
asynchronních operací delší, obzvláště v případě operací, jejichž vykonání trvá pouze krátkou dobu.
V běhovém prostředí je řada operací z podstaty synchronní nebo asynchronní a způsob jejich vykonávání nemůžete
zvolit. V Adobe AIR však existují tři typy operací, u kterých můžete zvolit, zda se budou provádět synchronně nebo
asynchronně:
• Operace třídy File a FileStream
Mnoho operací třídy File lze provést synchronně nebo asynchronně. Například metody ke kopírování nebo
odstraňování souboru nebo adresáře mají asynchronní verze. Tyto metody mají příponu „Async“, která je přidána
do názvu asynchronních verzí. Chcete-li například odstranit soubor asynchronně, zavolejte metodu
File.deleteFileAsync() namísto metody File.deleteFile().
Při použití objektu FileStream ke čtení ze souboru nebo zápisu do něj způsob otevření objektu FileStream určuje,
zda budou operace prováděny asynchronně. Pra asynchronní operace použijte metodu
FileStream.openAsync(). Zápis dat se provádí asynchronně. Čtení dat probíhá v dávkách, je tedy k dispozici jen
část. Naproti tomu v synchronním režimu objekt FileStream čte celý soubor, než bude vykonávání programu kódu
pokračovat.
• Operace místní databáze SQL
Při práci s místní databází SQL se všechny vykonávané operace spouští prostřednictvím objektu SQLConnection
buď v synchronním nebo asynchronním režimu. Chcete-li tyto operace vykonat asynchronně, otevřete připojení
k databázi pomocí metody SQLConnection.openAsync() namísto metody SQLConnection.open(). Když jsou
operace databáze spuštěny asynchronně, vykonávají se na pozadí. Databázový modul se za běhu ve smyčce snímku
vůbec nespustí, databázové operace tedy s daleko menší pravděpodobností způsobí problémy s vykreslováním.
Další strategie ke zvýšení výkonnosti s místní databází SQL najdete v tématu „Výkonnost databáze SQL“ na
stránce 89.
Poslední aktualizace 11.5.2012
75
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
• Samostatné shadery Pixel Bender
Třída ShaderJob umožňuje spustit obraz nebo nastavit data prostřednictvím shaderu Pixel Bender a přistupovat
k nezpracovaným datům. Ve výchozím nastavení, když zavoláte metodu ShaderJob.start(), shader se vykoná
asynchronně. Vykonání proběhne na pozadí mimo běh smyčky snímku. Chcete-li vynutit, aby se objekt ShaderJob
vykonával synchronně (což se nedoporučuje), zadejte do prvního parametru metody start() hodnotu true.
Navíc k těmto vestavěným mechanismům k asynchronnímu spouštění kódu můžete rovněž sestavit vlastní kód tak,
aby byl spouštěn asynchronně a ne synchronně. Pokud píšete kód k provedení potenciálně dlouho trvající úloze,
můžete sestavit kód tak, aby se vykonával po částech. Rozdělení kódu do částí umožní, aby se za běhu prováděly
operace vykreslení mezi vašimi bloky vykonání kódu, čímž budou problémy s vykreslením méně pravděpodobné.
Následuje několik technik k rozdělení kódu. Hlavní myšlenka všech těchto technik je taková, aby byl váš kód napsán
tak, aby se vždy provedla část práce. Můžete sledovat, co kód dělá a kdy přestane pracovat. Můžete použít například
objekt Timer k opakované kontrole, zda zbývá nějaká část práce zbývá a případně provést další část, dokud nebude vše
hotové.
Existuje několik zavedených vzorů ke strukturalizaci kódu, aby se tímto způsobem práce rozdělila. Následující články
a knihovny kódů tyto vzory popisují a poskytují kód, který vám může pomoci v jejich implementaci do aplikací:
• Asynchronní vykonávání jazyka ActionScript (článek Trevora McCauleye s dalšími souvisejícími podrobnostmi a
také několika příklady implementace)
• Analyzování a vykreslování velkého množství dat do aplikace Flash Player (článek Jesse Wardena se souvisejícími
podrobnostmi a příklady dvou přístupů: „builder pattern“ a „green threads“)
• Green Threads (článek Drewa Cumminse popisující techniku „green threads“ pomocí vzorového zdrojového
kódu)
• greenthreads (Otevřená knihovna k implementaci „green threads“ v jazyce ActionScript, jejímž autorem je Charlie
Hubbard. Další informace najdete v článku Rychlý start pro greenthreads.)
• Vlákna v jazyce ActionScript 3 na adrese http://www.adobe.com/go/learn_fp_as3_threads_cz (článek od Alexe
Haruiho s ukázkou implementace metody „pseudo vláken“)
Průhledná okna
U stolních aplikací prostředí AIR zvažte použití neprůhledného obdélníkového okna aplikace namísto průhledného
okna.
Chcete-li použít neprůhledné okno, pro výchozí okno stolní aplikace prostředí AIR nastavte následující hodnotu
v souboru XML deskriptoru aplikace:
<initialWindow>
<transparent>false</transparent>
</initialWindow>
Pro okna kódem aplikace vytvořte objekt NativeWindowInitOptions s vlastností transparent nastavenou na
hodnotu false (výchozí). Při vytváření objektu NativeWindow ho předejte do konstruktoru NativeWindow.
// NativeWindow: flash.display.NativeWindow class
var initOptions:NativeWindowInitOptions = new NativeWindowInitOptions();
initOptions.transparent = false;
var win:NativeWindow = new NativeWindow(initOptions);
Poslední aktualizace 11.5.2012
76
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
U komponenty Flex Window se ujistěte, že je vlastnost transparent nastavena na hodnotu false než zavoláte metodu
open() objektu Window.
// Flex window component: spark.components.Window class
var win:Window = new Window();
win.transparent = false;
win.open();
Průhledné okno může zobrazit část pracovní plochy uživatele nebo okna dalších aplikací, která jsou za oknem této
aplikace. Následkem toho se musí za běhu použít k vykreslení průhledného okna více zdrojů. Bez ohledu na to zda je
použito systémové nebo uživatelské ohraničení, obdélníkové neprůhledné okno nemá stejné vykreslovací zatížení.
Použijte průhledné okno pouze tehdy, když je důležité neobdélníkové zobrazení, nebo aby přes okno vaší aplikace byl
vidět obsah pozadí.
Vyhlazení tvarů vektorů
Vyhlazením tvarů zvýšíte rychlost vykreslování.
Na rozdíl od bitmap vyžaduje vykreslování vektorového obsahu mnoho výpočtů, zejména pro přechody a složité cesty,
které obsahují mnoho kontrolních bodů. Jako návrhář nebo vývojář se ujistěte, že tvary jsou dostatečně
optimalizované. Následující obrázek znázorňuje nezjednodušené cesty s mnoha kontrolními body:
Neoptimalizované cesty
Pomocí nástroje Vyhlazení v aplikaci Flash Professional lze odstranit dodatečné kontrolní body. Obdobný nástroj je k
dispozici v aplikaci Adobe® Illustrator®. Celkový počet bodů a cest lze zobrazit v panelu Informace o dokumentu.
Vyhlazení odstraní dodatečné kontrolní body, čímž se zmenší konečná velikost souboru SWF a zvýší se rychlost
vykreslování. Následující obrázek znázorňuje stejné cesty po vyhlazení:
Poslední aktualizace 11.5.2012
77
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost vykreslování
Optimalizované cesty
Pokud cesty příliš nezjednodušíte, touto optimalizací nedojde k žádné vizuální změně. Zjednodušením složitých cest
však můžete podstatně zvýšit průměrný kmitočet snímků konečné aplikace.
Poslední aktualizace 11.5.2012
78
79
Kapitola 6: Optimalizace interakcí v síti
Vylepšení aplikace pro interakce v síti
V aplikaci Flash Player 10.1 a prostředí AIR 2.5 byla zavedena sada nových funkcí pro optimalizaci sítě ve všech
platformách včetně cyklického ukládání do vyrovnávací paměti a inteligentního vyhledávání.
Cyklické ukládání do vyrovnávací paměti
Při načítání multimediálního obsahu do mobilních zařízení může dojít k potížím, které byste téměř nikdy neočekávali
u stolního počítače. Je například pravděpodobnější nedostatek místa na disku nebo paměti. Při načítání videa se ve
verzi aplikace Flash Player 10.1 a prostředí AIR 2.5 pro stolní počítače stáhne a uloží do mezipaměti na pevném disku
celý soubor FLV (nebo soubor MP4). Běhové prostředí pak video přehraje z tohoto souboru mezipaměti. Není
obvyklé, aby došlo místo na disku. Vznikne-li takováto situace, běhové prostředí stolního počítače zastaví přehrávání
videa.
U mobilního zařízení může dojít místo na disku snadněji. Pokud má zařízení nedostatek místa na disku, běhové
prostředí nezastaví přehrávání, jak je tomu u běhového prostředí ve stolním počítači. Namísto toho začne běhové
prostředí opakovaně používat soubor mezipaměti tak, že do něj bude znovu zapisovat od začátku souboru. Uživatel
může pokračovat ve sledování videa. Uživatel nemůže vyhledávat v části videa, která byla přepsána, s výjimkou začátku
souboru. Ve výchozím nastavení se cyklické ukládání do vyrovnávací paměti nespouští. Může být zahájeno během
přehrávání a také na začátku přehrávání, pokud je film větší než místo na disku nebo paměť RAM. Aby mohlo běhové
prostředí používat cyklické ukládání do mezipaměti, jsou nutné alespoň 4 MB paměti RAM nebo 20 MB místa na
disku.
Poznámka: Pokud má zařízení dostatek místa na disku, verze běhového prostředí pro mobilní zařízení se chová stejně
jako ve stolním počítači. Pamatujte, že vyrovnávací paměť v paměti RAM slouží jako záloha, pokud zařízení není
vybaveno diskem nebo je disk zaplněn. Omezení velikosti souboru mezipaměti a vyrovnávací paměti RAM lze nastavit
při kompilaci. Některé soubory MP4 mají strukturu, která vyžaduje, aby byl před spuštěním přehrávání stažen celý
soubor. Běhové prostředí tyto soubory zjistí a zabrání stažení, pokud není na disku dostatek místa a soubor MP4 nelze
přehrát. Je vhodné stažení takových souborů vůbec nepožadovat.
Jako vývojář pamatujte, že vyhledávání funguje pouze v rámci ohraničení streamu uloženého do mezipaměti. Metoda
NetStream.seek() někdy selhává, pokud je posun mimo rozsah, a v takovém případě je odeslána událost
NetStream.Seek.InvalidTime.
Inteligentní vyhledávání
Poznámka: Funkce inteligentního vyhledávání vyžaduje server Adobe® Flash® Media Server 3.5.3.
V aplikaci Flash Player 10.1 a prostředí AIR 2.5 bylo zavedeno nové chování zvané inteligentní vyhledávání, které
uživatelům nabízí lepší možnosti při přehrávání streamovaného videa. Pokud uživatel vyhledává požadované místo v
mezích vyrovnávací paměti, běhové prostředí používá obsah vyrovnávací paměti opakovaně, aby umožnilo okamžité
vyhledávání. V předchozích verzích běhového prostředí nebyl obsah vyrovnávací paměti používán opakovaně. Pokud
například uživatel přehrával video ze serveru se streamy, doba ukládání do vyrovnávací paměti byla nastavena na 20
sekund (NetStream.bufferTime) a uživatel se pokusil vyhledat 10 sekund směrem vpřed, běhové prostředí nevyužilo
10 sekund, které již byly načteny, ale odstranilo z vyrovnávací paměti všechna data. Toto chování vynucovalo v
běhovém prostředí mnohem častější požadavky na nová data ze serveru a u pomalých připojení způsobovalo nízkou
kvalitu přehrávání.
Poslední aktualizace 11.5.2012
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Optimalizace interakcí v síti
Následující obrázek znázorňuje chování vyrovnávací paměti v předchozích vydáních běhového prostředí. Vlastnost
bufferTime určuje počet sekund, které budou načteny předem, aby mohl být v případě ztráty připojení použit obsah
vyrovnávací paměti bez zastavení videa:
Vyrovnávací paměť
Přehrávací hlava
Chování vyrovnávací paměti před zavedením funkce inteligentního vyhledávání
Díky funkci inteligentního vyhledávání nyní běhové prostředí používá po posunutí videa uživatelem vyrovnávací
paměť k okamžitému vyhledávání směrem vzad nebo vpřed. Toto nové chování znázorňuje následující obrázek:
Vyrovnávací paměť
Přehrávací hlava
Vyhledávání směrem vpřed pomocí funkce inteligentního vyhledávání
Vyrovnávací paměť
Přehrávací hlava
Vyhledávání směrem vzad pomocí funkce inteligentního vyhledávání
Inteligentní vyhledávání používá vyrovnávací paměť opakovaně, když uživatel vyhledává směrem vpřed nebo vzad,
takže je přehrávání rychlejší a plynulejší. Jednou z výhod tohoto nového chování je úspora šířky pásma pro vydavatele
videa. V případě vyhledávání za hranicemi vyrovnávací paměti však dojde ke standardnímu chování a běhové
prostředí si vyžádá nová data ze serveru.
Poznámka: Toto chování se nevztahuje na postupné stahování videa.
Chcete-li použít inteligentní vyhledávání, nastavte vlastnost NetStream.inBufferSeek na hodnotu true.
Externí obsah
Rozdělte svou aplikaci na více souborů SWF.
Mobilní zařízení mohou mít omezený přístup k síti. Chcete-li obsah načíst rychle, rozdělte svou aplikaci na více
souborů SWF. Snažte se používat logiku kódu a datové zdroje v celé aplikaci opakovaně. Jako příklad uvádíme aplikaci,
která byla rozdělena na více souborů SWF, jak vyplývá z následujícího diagramu:
Poslední aktualizace 11.5.2012
80
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Optimalizace interakcí v síti
portfolio.swf
infos.swf
contact.swf
10 kB
10 kB
10 kB
main.swf
10 kB
preload.swf
Celková velikost 40 kB
Aplikace rozdělená do více souborů SWF
V tomto příkladu obsahuje každý soubor SWF svou vlastní kopii téže bitmapy. Této duplikaci se můžete vyhnout, když
použijete knihovnu RSL, jak je znázorněno v následujícím diagramu:
portfolio.swf
infos.swf
contact.swf
main.swf
preload.swf
Celková velikost 10 kB
Používání knihovny RSL
library.swf
10kB
Pomocí této metody byla načtena knihovna RSL, aby byla bitmapa k dispozici ostatním souborům SWF. Třída
ApplicationDomain obsahuje všechny definice tříd, které byly načteny, a zpřístupňuje je za běhu prostřednictvím
metody getDefinition().
Knihovna RSL může také obsahovat veškerou logiku kódu. Celou aplikaci lze aktualizovat za běhu bez opětovné
kompilace. Následující kód načte knihovnu RSL a extrahuje definici obsaženou v souboru SWF za běhu. Tuto metodu
lze použít pro písma, bitmapy, zvuky nebo libovolnou třídu jazyka ActionScript:
Poslední aktualizace 11.5.2012
81
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Optimalizace interakcí v síti
// Create a Loader object
var loader:Loader = new Loader();
// Listen to the Event.COMPLETE event
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadingComplete );
// Load the SWF file
loader.load(new URLRequest("library.swf") );
var classDefinition:String = "Logo";
function loadingComplete(e:Event ):void
{
var objectLoaderInfo:LoaderInfo = LoaderInfo ( e.target );
// Get a reference to the loaded SWF file application domain
var appDomain:ApplicationDomain = objectLoaderInfo.applicationDomain;
// Check whether the definition is available
if ( appDomain.hasDefinition(classDefinition) )
{
// Extract definition
var importLogo:Class = Class ( appDomain.getDefinition(classDefinition) );
// Instantiate logo
var instanceLogo:BitmapData = new importLogo(0,0);
// Add it to the display list
addChild ( new Bitmap ( instanceLogo ) );
} else trace ("The class definition " + classDefinition + " is not available.");
}
Získání definice lze usnadnit načtením definic třídy v doméně aplikace načítajícího souboru SWF:
Poslední aktualizace 11.5.2012
82
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Optimalizace interakcí v síti
// Create a Loader object
var loader:Loader = new Loader();
// Listen to the Event.COMPLETE event
loader.contentLoaderInfo.addEventListener ( Event.COMPLETE, loadingComplete );
// Load the SWF file
loader.load ( new URLRequest ("rsl.swf"), new LoaderContext ( false,
ApplicationDomain.currentDomain) );
var classDefinition:String = "Logo";
function loadingComplete ( e:Event ):void
{
var objectLoaderInfo:LoaderInfo = LoaderInfo ( e.target );
// Get a reference to the current SWF file application domain
var appDomain:ApplicationDomain = ApplicationDomain.currentDomain;
// Check whether the definition is available
if (appDomain.hasDefinition( classDefinition ) )
{
// Extract definition
var importLogo:Class = Class ( appDomain.getDefinition(classDefinition) );
// Instantiate it
var instanceLogo:BitmapData = new importLogo(0,0);
// Add it to the display list
addChild ( new Bitmap ( instanceLogo ) );
} else trace ("The class definition " + classDefinition + " is not available.");
}
Nyní je možné třídy dostupné v načteném souboru SWF použít voláním metody getDefinition() v doméně
aktuální aplikace. Přístup k těmto třídám lze také získat voláním metody getDefinitionByName(). Tato metoda šetří
šířku pásma tím, že písma a velké datové zdroje načte pouze jednou. Datové zdroje nejsou nikdy exportovány v
žádných jiných souborech SWF. Jediným omezením je, že aplikace musí být testována a spouštěna prostřednictvím
souboru loader.swf. Tento soubor načte nejprve datové zdroje a pak jednotlivé soubory SWF, které tvoří aplikaci.
Chyby vstupu a výstupu
Zadejte zpracování událostí a chybové zprávy pro chyby vstupu a výstupu.
U mobilního zařízení může být síť méně spolehlivá než u stolního počítače připojeného k vysokorychlostnímu
Internetu. Přístup k externímu obsahu v mobilních zařízeních má dvě omezení – dostupnost a rychlost. Proto se
přesvědčte, zda mají datové zdroje malý objem a přidejte ovladače pro každou událost IO_ERROR, které poskytnou
uživateli zpětnou vazbu.
Představte si například, že uživatel prochází váš web prostřednictvím mobilního zařízení a mezi dvěma stanicemi
metra náhle ztratí síťové připojení. V okamžiku ztráty připojení byl načítán dynamický datový zdroj. U stolního
počítače můžete zabránit zobrazení chyby za běhu pomocí prázdného posluchače události, protože k takové situaci
téměř nikdy nedojde. Avšak u mobilního zařízení musíte tuto situaci řešit složitěji než jednoduchým prázdným
posluchačem.
Poslední aktualizace 11.5.2012
83
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Optimalizace interakcí v síti
Následující kód neodpovídá na chybu vstupu nebo výstupu. Tak jak je uveden, jej nepoužívejte:
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener( Event.COMPLETE, onComplete );
addChild( loader );
loader.load( new URLRequest ("asset.swf" ) );
function onComplete( e:Event ):void
{
var loader:Loader = e.currentTarget.loader;
loader.x = ( stage.stageWidth - e.currentTarget.width ) >> 1;
loader.y = ( stage.stageHeight - e.currentTarget.height ) >> 1;
}
Vhodnější je takové selhání zpracovat a zadat chybovou zprávu pro uživatele. Následující kód je zpracuje správně:
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener ( Event.COMPLETE, onComplete );
loader.contentLoaderInfo.addEventListener ( IOErrorEvent.IO_ERROR, onIOError );
addChild ( loader );
loader.load ( new URLRequest ("asset.swf" ) );
function onComplete ( e:Event ):void
{
var loader:Loader = e.currentTarget.loader;
loader.x = ( stage.stageWidth - e.currentTarget.width ) >> 1;
loader.y = ( stage.stageHeight - e.currentTarget.height ) >> 1;
}
function onIOError ( e:IOErrorEvent ):void
{
// Show a message explaining the situation and try to reload the asset.
// If it fails again, ask the user to retry when the connection will be restored
}
Nezapomeňte uživateli nabídnout způsob, jakým lze obsah načíst znovu. Toto chování lze implementovat v ovladači
události onIOError().
Flash Remoting
Pomocí technologie Flash Remoting a formátu AMF lze optimalizovat datovou komunikaci mezi klientem a
serverem.
K načtení vzdáleného obsahu do souborů SWF můžete použít jazyk XML. Soubor XML je prostý text, který běhové
prostředí načte a analyzuje. Jazyk XML pracuje nejlépe u aplikací, které načítají omezená množství obsahu. Pokud
vyvíjíte aplikaci, která načítá velký objem obsahu, zvažte možnost použití technologie Flash Remoting a formátu AMF
(Action Message Format).
Poslední aktualizace 11.5.2012
84
85
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Optimalizace interakcí v síti
Formát AMF je binární formát, který slouží ke sdílení dat mezi serverem a běhovým prostředím. Při použití formátu
AMF se zmenšuje objem dat a zvyšuje rychlost přenosu. Vzhledem k tomu, že formát AMF je nativní formát běhového
prostředí, odesláním dat AMF běhovému prostředí se vyhnete serializaci a deserializaci na straně klienta, které jsou
náročné na paměť. Tyto úkoly provádí brána vzdálené komunikace. Při odesílání datového typu jazyka ActionScript
na server provádí brána vzdálené komunikace serializaci na straně serveru za vás. Tato brána vám rovněž zasílá
odpovídající datový typ. Tento typ dat je třída vytvořená na serveru, která nabízí sadu metod, jež lze volat z běhového
prostředí. K branám Flash Remoting patří ZendAMF, FluorineFX, WebORB a BlazeDS – oficiální brána technologie
Flash Remoting typu Open Source od společnosti Adobe založená na jazyce Java.
Následující obrázek znázorňuje koncept technologie Flash Remoting:
ZendAMF
HTTP
Web ORB
RubyAMF
AMF
FluorineFX
Služba
(třída PHP,
Java, C# ...)
BlazeDS
Flash Remoting
V následujícím příkladu je pro připojení k bráně Flash Remoting použita třída NetConnection:
// Create the NetConnection object
var connection:NetConnection = new NetConnection ();
// Connect to a Flash Remoting gateway
connection.connect ("http://www.yourserver.com/remotingservice/gateway.php");
// Asynchronous handlers for incoming data and errors
function success ( incomingData:* ):void
{
trace( incomingData );
}
function error ( error:* ):void
{
trace( "Error occured" );
}
// Create an object that handles the mapping to success and error handlers
var serverResult:Responder = new Responder (success, error);
// Call the remote method
connection.call ("org.yourserver.HelloWorld.sayHello", serverResult, "Hello there ?");
Připojení k bráně vzdálené komunikace je přímé. Avšak používání technologie Flash Remoting lze ještě více usnadnit
pomocí třídy RemoteObject obsažené v sadě Adobe® Flex® SDK.
Poznámka: Externí soubory SWC, například soubory z prostředí Flex, lze použít v projektu aplikace Adobe® Flash®
Professional. Budete-li používat soubory SWC, můžete pracovat s třídou RemoteObject a jejími závislostmi, aniž byste
používali zbývající části sady Flex SDK. Pokročilí vývojáři mohou dokonce podle potřeby komunikovat s bránou vzdálené
komunikace přímo prostřednictvím původní třídy Socket.
Poslední aktualizace 11.5.2012
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Optimalizace interakcí v síti
Zbytečné síťové operace
Uložte datové zdroje po načtení do místní mezipaměti namísto opakovaného načítání vždy, když jsou potřeba.
Pokud vaše aplikace načítá datové zdroje, například média nebo jiná data, uložte je do mezipaměti místního zařízení.
Pro datové zdroje, které se zřídkakdy mění, zvažte aktualizaci mezipaměti v určitých intervalech. Vaše aplikace
například může kontrolovat, zda existuje nová verze souboru obrazu jednou denně, nebo může kontrolovat aktuální
data jednou za dvě hodiny.
Datové zdroje můžete ukládat do mezipaměti několika způsoby v závislosti na typu a povaze datového zdroje:
• Soubory datových zdrojů médií, například obrazů a videí, uložte do souborového systému pomocí tříd File a
FileStream.
• Jednotlivé datové hodnoty nebo malé datové množiny uložte jako místní sdílené objekty pomocí třídy
SharedObject.
• Větší datové množiny uložte do místní databáze nebo data serializujte a uložte je do souboru.
K ukládání datových hodnot do mezipaměti můžete použít otevřený projekt AS3CoreLib obsahující třídu
ResourceCache, která provádí načítání a ukládání dat z a do mezipaměti za vás.
Poslední aktualizace 11.5.2012
86
87
Kapitola 7: Práce s médii
Video
Informace o optimalizaci výkonu videa v mobilních zařízeních naleznete na webu Adobe Developer Connection v
tématu Optimalizace webového obsahu pro mobilní zařízení.
Zaměřte se zejména na tyto oddíly:
• Přehrávání videa v mobilních zařízeních
• Ukázky kódu
Tyto oddíly obsahují informace o vývoji přehrávačů videa pro mobilní zařízení, například:
• Pokyny pro kódování videa
• Osvědčené postupy
• Profilování výkonu přehrávače videa
• Implementace referenčního přehrávače videa
StageVideo
Třída StageVideo umožňuje využívat k prezentaci videa hardwarovou akceleraci.
Informace o používání objektu StageVideo naleznete v tématu Použití třídy StageVideo pro hardwarově
akcelerovanou prezentaci v Příručce pro vývojáře jazyka ActionScript 3.0.
Zvuk
Počínaje aplikací Flash Player 9.0.115.0 a prostředím AIR 1.0 může běhové prostředí přehrávat soubory AAC (AAC
Main, AAC LC a SBR). Používání souborů AAC namísto souborů MP3 představuje jednoduchý způsob optimalizace.
Formát AAC nabízí při stejném datovém toku lepší kvalitu a menší velikost souboru než formát MP3. Omezením
velikosti souboru lze ušetřit šířku pásma, což je u mobilních zařízení bez vysokorychlostního připojení k internetu
důležité.
Hardwarové dekódování zvuku
Podobně jako dekódování videa i dekódování zvuku vyžaduje velké množství cyklů CPU a lze jej optimalizovat
využitím hardwaru dostupného v zařízení. Aplikace Flash Player 10.1 a prostředí AIR 2.5 mohou zjistit a použít
hardwarové zvukové ovladače, čímž dojde ke zvýšení výkonu při dekódování souborů AAC (profily LC, HE/SBR) a
souborů MP3 (není podporován formát PCM). Lze tak velmi výrazně omezit využití CPU, v důsledku čehož se sníží
spotřeba baterie a uvolní CPU pro jiné operace.
Poslední aktualizace 11.5.2012
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Práce s médii
Poznámka: Kvůli chybějící hardwarové podpoře ve většině zařízení není v zařízeních při použití formátu AAC
podporován profil AAC Main.
Hardwarové dekódování zvuku je transparentní pro uživatele i vývojáře. Pří spuštění přehrávání zvukových streamů
běhové prostředí stejně jako u videa nejprve zjistí hardware. Pokud je k dispozici hardwarový ovladač a formát zvuku
je podporován, bude zvuk dekódován hardwarově. Je však možné, že i když příchozí stream AAC nebo MP3 lze
dekódovat prostřednictvím hardwaru, hardware někdy nedokáže zpracovat všechny efekty. V závislosti na omezeních
hardwaru nemusí hardware zpracovat například míchání a převzorkování zvuku.
Poslední aktualizace 11.5.2012
88
89
Kapitola 8: Výkonnost databáze SQL
Návrh aplikace pro výkonnou databázi
Neměňte vlastnost text objektu SQLStatement po jeho vykonání. Namísto toho použijte instanci SQLStatement pro
každý příkaz SQL a použijte parametry příkazu, abyste zajistili různé hodnoty.
Před provedením jakéhokoliv příkazu jej SQL připraví (kompiluje) k určení kroků, které jsou provedeny interně pro
provedení příkazu. Když voláte SQLStatement.execute() na instanci SQLStatement, která nebyla dříve provedena,
příkaz je před provedením automaticky připraven. U dalších volání metody execute(), dokud nebyla vlastnost
SQLStatement.text změněna, je příkaz stále připraven. Proto je proveden rychleji.
Pro získání maximálních výhod díky opětovnému použití příkazů, jestliže se mezi provedeními příkazu hodnoty
změnily, použijte parametry příkazu k vlastnímu nastavení příkazu. (Parametry příkazu jsou určeny pomocí vlastnosti
asociativního poleSQLStatement.parameters.) Oproti změně vlastnosti instance SQLStatement textse při změně
hodnoty parametrů příkazu nevyžaduje od runtime opětovné připravení příkazu.
Když opětovně používáte instanci SQLStatement, vaše aplikace musí uložit referenci na instanci SQLStatement po
jejím připravení. Po uchování reference na danou instanci deklarujte danou proměnou jako proměnou rozsahu třídy,
nikoliv jako proměnnou rozsahu funkce. Jedním dobrým způsobem jak z instance SQLStatement vytvořit proměnnou
rozsahu třídy je strukturovat vaši aplikaci tak, aby byl příkaz SQL zabalen do jediné třídy. Skupina příkazů, které jsou
provedeny v kombinaci, může být také zabalena do jediné třídy. (Tato technika je známa jako příkazový vzorek návrhu
(Command design pattern).) Definováním instancí jako členových proměnných dané třídy zůstanou tyto tak dlouho,
dokud instance třídy objektu zabalení existuje v aplikaci. Minimálně můžete jednoduše definovat proměnou
obsahující instanci SQLStatement mimo funkci, takže je instance uchována v paměti. Instanci SQLStatement
deklarujte například jako členovou proměnnou ve třídě ActionScript nebo jako ne-funkční proměnnou v souboru
JavaScript. Poté můžete nastavit hodnoty parametru příkazů a volat jeho metodu execute(), pokud si přejete dotaz
skutečně spustit.
Použitím indexů databáze zvýšíte rychlost porovnávání a řazení dat.
Když vytvoříte index pro sloupec, databáze uloží kopii dat tohoto sloupce. Tato kopie se číselně nebo abecedně
uspořádá. Toto třídění umožňuje databázi rychle porovnávat hodnoty (například při použití operátoru rovnosti) a
řadit výsledná data pomocí klauzule ORDER BY.
Indexy databáze jsou neustále aktualizovány, což mírně zpomaluje operace měnící data (VLOŽIT nebo
AKTUALIZOVAT) v dané tabulce. Zvýšení rychlosti získávání dat může být značné. Z důvodu tohoto kompromisu
výkonnosti jednoduše indexujte každý sloupec tabulky. Pro definování indexů použijte raději strategii. Pomocí
následujících pokynů naplánujte strategii indexování:
• indexujte sloupce, které se používají při spojování tabulek, v klauzuli WHERE nebo ORDER BY,
• pokud jsou sloupce často používány společně, indexujte je společně pomocí jednoho indexu,
• pro sloupec obsahující textová data, která získáte při abecedním řazení, určete pro index kompletování COLLATE
NOCASE.
Zvažte předem připravené kompilování příkazů SQL, když je aplikace neaktivní.
Poslední aktualizace 11.5.2012
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost databáze SQL
První vykonání příkazů SQL je pomalejší, protože se text SQL připravuje (kompiluje) databázovým modulem. Protože
příprava a provedení příkazu může být náročná, je jednou strategií předem načíst počáteční data a poté provést jiné
příkazy na pozadí.
1 Načtěte data, která aplikace potřebuje nejdříve..
2 Po dokončení počátečních spouštěcích operací aplikace nebo při další „nečinnosti“ aplikace proveďte další příkazy.
Přepokládejme například, že vaše aplikace vůbec nepřistupuje k databázi, aby se zobrazila úvodní obrazovka. V tomto
případě počkejte, dokud se tato obrazovka neobjeví, než otevřete připojení k databázi. Nakonec vytvořte instance
SQLStatement a vykonejte vše, co můžete.
Alternativně předpokládejme, že aplikace při spuštění okamžitě zobrazí některá data, například výsledek určitého
dotazu. V tomto případě pokračujte a pro daný dotaz proveďte instanci SQLStatement. Po načtení a zobrazení
počátečních dat vytvořte instance SQLStatement pro další operace databáze a je-li to možné, proveďte jiné příkazy,
které jsou potřeba později.
Pokud v praxi používáte instance SQLStatement, další čas, který je vyžadován k přípravě příkazu, nastane pouze
jednou. Pravděpodobně nemá značný vliv na celkový výkon.
Seskupte více operací změn dat SQL do jedné transakce.
Předpokládejme, že provádíte mnoho příkazů SQL, které zahrnují přidání nebo změnu dat (příkazy INSERT nebo
UPDATE). Můžete významně vylepšit výkon, a to provedením všech příkazů v rámci explicitní transakce. Jestliže
explicitně nezahájíte transakci, každý z příkazů běží ve vlastní automaticky vytvořené transakci. Po dokončení spuštění
každé transakce (každého příkazu) zapíše runtime výsledná data do souboru databáze na disk.
Na druhou stranu zvažte, co se stane, pokud explicitně vytvoříte transakci a provedete příkazy v kontextu dané
transakce. Runtime provede všechny změny v paměti a poté je všechny najedou zapíše do souboru databáze při
spuštění transakce. Zapsání dat na disk obvykle zabírá nejvíce času z operace. Proto zapisování na disk najednou spíše
než pro každý příkaz SQL může výrazně zlepšit výkon.
Rozsáhlé výsledky dotazu SELECT zpracujte po částech pomocí metod execute() (s parametrem prefetch) a
next() třídy SQLStatement.
Předpokládejme, že jste vykonali příkaz SQL, který získal rozsáhlou množinu výsledků. Aplikace potom ve smyčce
zpracovává každý řádek dat. Například data formátuje nebo z nich vytváří objekty. Zpracování takovýchto dat může
trvat dlouho, což by mohlo způsobit problémy při vykreslování, například zablokovanou nebo neodpovídající
obrazovku. Tak, jak je popsáno v části „Asynchronní operace“ na stránce 75, jedním řešením je rozdělit práci do částí.
API databáze SQL usnadňuje rozdělení zpracování dat.
Metoda execute() třídy SQLStatement má volitelný parametr prefetch (první parametr). Pokud zadáte nějakou
hodnotu, určuje maximální počet řádků výsledku, které po vykonání příkazu databáze vrátí:
dbStatement.addEventListener(SQLEvent.RESULT, resultHandler);
dbStatement.execute(100); // 100 rows maximum returned in the first set
Jakmile je vrácena první sada výsledných dat, můžete pokračovat ve vykonávání příkazu zavoláním metody next(),
čímž získáte další sadu řádků výsledku. Podobně jako metoda execute() metoda next() používá parametr prefetch
k určení maximálního počtu řádků, které budou vráceny:
Poslední aktualizace 11.5.2012
90
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost databáze SQL
// This method is called when the execute() or next() method completes
function resultHandler(event:SQLEvent):void
{
var result:SQLResult = dbStatement.getResult();
if (result != null)
{
var numRows:int = result.data.length;
for (var i:int = 0; i < numRows; i++)
{
// Process the result data
}
if (!result.complete)
{
dbStatement.next(100);
}
}
}
Dokud nebudou načtena všechna data, můžete pokračovat ve volání metody next(). Tak jak je zobrazeno
v předchozím výpisu, můžete stanovit, zda byla všechna data načtena. Zkontrolujte vlastnost complete objektu
SQLResult, který je vytvořen po každém dokončení metody execute() nebo next().
Poznámka: Pomocí parametru prefetch a metody next() rozdělte zpracování výsledných dat. Nepoužívejte tento
parametr a metodu k omezení výsledků dotazu na část výsledné množiny. Pokud chcete načíst pouze podmnožinu řádků
z výsledné množiny příkazu, použijte klauzuli LIMIT příkazu SELECT. Pokud je množina výsledků příliš velká, můžete
stále použít parametr prefetch a metodu next() k rozdělení zpracování výsledků.
Zvažte použití více asynchronních objektů SQLConnection s jednou databází k provedení více příkazů současně.
Když je objekt SQLConnection připojen k databázi pomocí metody openAsync(), je spuštěn na pozadí spíše než
v hlavním vlákně vykonávání. Každý objekt SQLConnection je navíc spuštěn ve svém vlastním vlákně na pozadí.
Použitím více objektů SQLConnection můžete efektivně spouštět více příkazů SQL současně.
Tento přístup má však i své nevýhody. Nejdůležitější je ta, že každý další objekt SQLConnection vyžaduje další paměť.
Souběžné vykonávání však navíc může znamenat větší zatížení procesoru, zvláště na počítačích, které mají jen jeden
procesor nebo jen jednojádrový procesor. Z těchto důvodů se tento přístup nedoporučuje při použití v mobilních
zařízeních.
Dalším problémem je to, že případné výhody opětovného použití objektů SQLStatements mohou být ztraceny, protože
objekt SQLStatement je svázán s jedním objektem SQLConnection. Z toho důvodu nelze objekt SQLStatement znovu
použít, pokud se jeho asociovaný objekt SQLConnection již používá.
Pokud chcete použít více objektů SQLConnection připojených k jedné databázi, pamatujte, že každý vykonává své
příkazy ve své vlastní transakci. Nezapomeňte na tyto oddělené transakce v žádném kódu měnícím data, například
přidávajícím, upravujícím nebo odstraňujícím data.
Paul Robertson vytvořil otevřenou knihovnu, která vám pomůže využít výhod použití více objektů SQLConnection a
současně minimalizovat možné nevýhody. Knihovna používá fond objektů SQLConnection a spravuje asociované
objekty SQLStatement. Tímto způsobem je zajištěno, aby byly objekty SQLStatement znovu použity a více objektů
SQLConnection bylo k dispozici k vykonání více příkazů současně. Další informace a odkaz na stažení této knihovny
viz http://probertson.com/projects/air-sqlite/.
Poslední aktualizace 11.5.2012
91
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost databáze SQL
Optimalizace databázových souborů
Neměňte schéma databáze.
Je-li to možné, vyhněte se po vložení dat do tabulek databáze změně schématu (struktury tabulky) databáze. Běžně je
soubor databáze strukturován s definicemi tabulky na začátku souboru. Když otevřete připojení k databázi, runtime
načte tyto definice. Když přidáte data do tabulek databáze, data jsou přidána do souboru za definiční data tabulky.
Pokud ale provedete změny ve schématu, dojde ke smíchání definičních dat nové tabulky s daty tabulky v souboru
databáze. Například přidání sloupce do tabulky nebo přidání nové tabulky může způsobit smíchání typů dat. Pokud
nejsou definiční data tabulky umístěná na začátku databázového souboru, bude otevření připojení k databázi trvat
déle. Připojení je pomalejší, protože běhu aplikace trvá déle načítání definičních dat tabulky z různých částí souboru.
Použijte metodu SQLConnection.compact() k optimalizaci databáze po změnách schématu.
Pokud musíte změnit schéma, můžete po dokončení změn volat metodu SQLConnection.compact(). Tato operace
změní strukturu souboru databáze tak, že definiční data tabulky budou všechna umístěna na začátku souboru. Operace
compact() může nicméně zabrat mnoho času, zvláště při narůstající velikosti souboru databáze.
Zbytečné zpracování databází za běhu
Používejte ve svém příkazu SQL zcela kvalifikovaný název tabulky (včetně názvu databáze).
Vždy v příkazu explicitně určete název databáze spolu s každým názvem tabulky. (Použijte „main“ (hlavní), jedná-li
se o hlavní databázi). Následující kód například obsahuje explicitní název databáze main:
SELECT employeeId
FROM main.employees
Explicitní určení názvu databáze zabraňuje, aby se za běhu musela kontrolovat každá připojená databáze, zda obsahuje
odpovídající tabulku. Zabraňuje také tomu, že runtime zvolí špatnou databázi. Tímto pravidlem se řiďte, i pokud je
objekt SQLConnection připojen pouze k jediné databázi. Objekt SQLConnection je v pozadí také připojen
k přechodné databázi, která je přístupná prostřednictvím příkazů SQL.
Použijte v příkazech SQL INSERT a SELECT explicitní názvy sloupce.
Následující příklady znázorňují explicitní použití názvů sloupců:
INSERT INTO main.employees (firstName, lastName, salary)
VALUES ("Bob", "Jones", 2000)
SELECT employeeId, lastName, firstName, salary
FROM main.employees
Porovnejte předcházející příklady s následujícími. Nepoužívejte tento styl kódu:
Poslední aktualizace 11.5.2012
92
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost databáze SQL
-- bad because column names aren't specified
INSERT INTO main.employees
VALUES ("Bob", "Jones", 2000)
-- bad because it uses a wildcard
SELECT *
FROM main.employees
Bez explicitních názvů sloupů se musí za běhu provádět přídavná práce ke zjištění názvů sloupců. Pokud příkaz
SELECT používá zástupné znaky místo explicitních sloupců, musí běh aplikace načítat další data. Tato přídavná data
vyžadují přídavné zpracování vytváří přídavné instance objektů, které nejsou potřebné.
Vyhněte se vícenásobnému spojování stejné tabulky v příkazu, pokud tabulku neporovnáváte s ní samou.
S narůstajícím počtem příkazů SQL se může stát, že se neúmyslně připojíte k databázové tabulce vícekrát. Často lze
stejného výsledku dosáhnout pouze jedním použitím tabulky. K vícenásobnému připojení k jedné tabulce může dojít,
používáte-li v dotazu jeden nebo více pohledů. Můžete se například připojit k tabulce za účelem dotazu, ale také za
účelem zobrazení dat z této tabulky. Tyto dvě operace způsobí více než jedno připojení.
Efektivní syntaxe jazyka SQL
K zahrnutí tabulky do dotazu použijte příkaz JOIN (v klauzuli FROM) namísto dílčího dotazu v klauzuli WHERE. Tento
tip platí, i pokud potřebujete data tabulky k filtrování nikoliv pro množinu výsledků.
Spojování více tabulek v klauzuli FROM pracuje rychleji než použití dílčího dotazu v klauzuli WHERE.
Nepoužívejte příkazy SQL, které nevyužívají indexy. Tyto příkazy zahrnují používání souhrnných funkcí v dílčím
dotazu, příkaz UNION v dílčím dotazu nebo klauzuli ORDER BY uvedenou společně s příkazem UNION.
Index může značně zvýšit rychlost zpracování dotazu SELECT. Určitá syntaxe SQL však brání databázi používat indexy
a vynutí, aby použila aktuální data k operacím vyhledávání nebo řazení.
Vyhněte se použití operátoru LIKE zvláště se zástupným znakem na začátku LIKE('%XXXX%').
Protože operace LIKE podporuje vyhledávání se zástupnými znaky, provedení je pomalejší než použití porovnávání
přesné shody. Obzvláště pokud zahájíte řetězec vyhledávání zástupným znakem, nemůže databáze indexy při
vyhledávání použít vůbec. Databáze musí místo toho prohledat kompletní text v každém řádku tabulky.
Vyhněte se operátoru IN. Pokud jsou možné hodnoty známy dopředu, operaci IN lze zapsat pomocí operátorů AND
nebo OR, aby bylo vykonávání rychlejší.
Druhý z následujících dvou příkazů proběhne rychleji. Je rychlejší, protože používá jednoduché výrazy rovnosti
v kombinaci s operátorem OR namísto použití příkazů IN() nebo NOT IN():
-- Slower
SELECT lastName, firstName, salary
FROM main.employees
WHERE salary IN (2000, 2500)
-- Faster
SELECT lastName, firstName, salary
FROM main.employees
WHERE salary = 2000
OR salary = 2500
Poslední aktualizace 11.5.2012
93
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Výkonnost databáze SQL
Zvažte alternativní formy příkazu SQL ke zlepšení výkonnosti.
Jak bylo předvedeno v předchozích příkladech, způsob zápisu příkazu SQL může rovněž ovlivnit výkonnost databáze.
Často existuje více způsobů k zápisu příkazu SELECT jazyka SQL k načtení určité sady výsledků. V některých
případech běží jeden přístup značně rychleji než jiný. Navíc k předcházejícím návrhům můžete získat další informace
o různých příkazech SQL a jejich výkonnosti v materiálech, které se specializují na jazyk SQL.
Výkonnost příkazů SQL
Přímým porovnáním alternativních příkazů SQL zjistěte, který je rychlejší.
Nejlepší způsob porovnávání výkonnosti více verzí příkazu SQL je jejich přímé vyzkoušení s vaší databází a daty.
Následující vývojové nástroje poskytují časy vykonání příkazů SQL. Použijte je k porovnání rychlosti alternativních
verzí příkazů:
• Run! (vývojový a testovací nástroj pro dotazy AIR SQL, jeho autorem je Paul Robertson)
• Lita (administrativní nástroj SQLite, autorem je David Deraedt)
Poslední aktualizace 11.5.2012
94
95
Kapitola 9: Porovnávání a nasazování
Porovnávání
Existuje řada nástrojů pro testování výkonnosti aplikace. Můžete použít třídu Stats a třídu PerformanceTest, které
vytvořili členové komunity Flash. Také můžete použít funkci profilování aplikace Adobe® Flash® Builder™ a nástroj
FlexPMD.
Třída Stats
Chcete-li profilovat kód za běhu pomocí vydané verze běhového prostředí bez použití externího nástroje, můžete
použít třídu Stats, kterou vytvořil uživatel mr. doob z komunity Flash. Třídu Stats lze stáhnout na následující adrese:
https://github.com/mrdoob/Hi-ReS-Stats.
Třída Stats umožňuje sledovat následující hodnoty:
• Počet vykreslených snímků za sekundu (čím je číslo vyšší, tím lépe).
• Počet milisekund potřebných k vykreslení snímku (čím je číslo nižší, tím lépe).
• Množství paměti, které kód používá. Pokud se hodnota v každém snímku zvyšuje, je možné, že v aplikaci dochází
k úniku paměti. Možnému úniku paměti je třeba věnovat pozornost.
• Maximální množství paměti, které aplikace používala.
Po stažení lze třídu Stats použít pomocí tohoto kompaktního kódu:
import net.hires.debug.*;
addChild( new Stats() );
Při použití podmíněné kompilace v aplikaci Adobe® Flash® Professional nebo Flash Builder můžete objekt Stats
povolit:
CONFIG::DEBUG
{
import net.hires.debug.*;
addChild( new Stats() );
}
Přepnutím hodnoty konstanty DEBUG lze kompilaci objektu Stats povolit nebo zakázat. Stejným postupem je možné
nahradit jakoukoli logiku kódu, kterou nechcete v aplikaci kompilovat.
Třída PerformanceTest
Grant Skinner vytvořil nástroj pro profilování provádění kódu ActionScript, který lze integrovat do pracovních
postupů testování jednotek. Vlastní třídu předáte třídě PerformanceTest, která na kódu provede sadu testů. Třída
PerformanceTest umožňuje snadné testování různých přístupů. Třídu PerformanceTest je možné stáhnout z těchto
stránek: http://www.gskinner.com/blog/archives/2009/04/as3_performance.html.
Funkce profilování aplikace Flash Builder
Součástí aplikace Flash Builder je funkce profilování, která umožňuje velmi detailní testování výkonnosti kódu.
Poslední aktualizace 11.5.2012
OPTIMALIZACE VÝKONU PRO PLATFORMU FLASH
Porovnávání a nasazování
Poznámka: Pro přístup k funkci profilování použijte ladicí verzi aplikace Flash Player, v opačném případě se zobrazí
chybové hlášení.
Funkci profilování lze použít i pro obsah vytvořený v aplikaci Adobe Flash Professional. V takovém případě je třeba
načíst kompilovaný soubor SWF z projektu ActionScript nebo Flex do aplikace Flash Builder a následně pro něj budete
moci použít funkci profilování. Další informace o funkci profilování naleznete v tématu Profilování aplikací Flex na
stránce Používání aplikace Flash Builder 4.
FlexPMD
Oddělení technických služeb společnosti Adobe vydalo nástroj nazvaný FlexPMD, který umožňuje provést audit
kvality kódu ActionScript 3.0. FlexPMD je nástroj určený pro jazyk ActionScript, který je podobný nástroji JavaPMD.
Nástroj FlexPMD provádí audit zdrojové složky jazyka ActionScript 3.0 nebo prostředí Flex, čímž zvyšuje kvalitu
kódu. Zjišťuje nežádoucí postupy při psaní kódu, jako je nepoužívaný kód, příliš složitý kód, příliš dlouhý kód a
nesprávné použití životního cyklu komponenty Flex.
FlexPMD je otevřený projekt společnosti Adobe, který je dostupný na následující adrese:
http://opensource.adobe.com/wiki/display/flexpmd/FlexPMD. Zásuvný modul Eclipse je rovněž dostupný na
následující adrese: http://opensource.adobe.com/wiki/display/flexpmd/FlexPMD+Eclipse+plugin.
Nástroj FlexPMD usnadňuje provádění auditu kódu a pomáhá zajistit čistý a optimalizovaný kód. Velká výhoda
nástroje FlexPMD spočívá v jeho rozšiřitelnosti. Jako vývojář můžete vytvořit vlastní sady pravidel pro audit
jakéhokoli kódu. Můžete například vytvořit sadu pravidel, jež zjišťují nadměrné používání filtrů nebo jakýkoli jiný
nežádoucí postup při psaní kódu, který chcete zachytit.
Nasazování
Při exportu konečné verze aplikace v aplikaci Flash Builder je důležité zajistit, aby byla exportována verze vydání. Při
exportu verze vydání jsou ze souboru SWF odstraněny informace ladění. Odstraněním informací ladění se zmenší
velikost souboru SWF a zrychlí běh aplikace.
Chcete-li exportovat verzi vydání aplikace, použijte volbu Export Release Build (Exportovat verzi vydání) v panelu
Project (Projekt) v aplikaci Flash Builder.
Poznámka: Při kompilaci projektu v aplikaci Flash Professional nelze zvolit mezi verzí vydání a ladicí verzi.
Kompilovaný soubor SWF je implicitně verze vydání.
Poslední aktualizace 11.5.2012
96

Podobné dokumenty

Stáhnout PDF s nápovědou

Stáhnout PDF s nápovědou Vývoj aplikací Adobe® AIR™ 1.1 pomocí programu Adobe® Flash® CS4 Professional Pokud je tato příručka distribuovaná se softwarem, u kterého je zahrnuta i smlouva s koncovým uživatelem, je tato příru...

Více

Stáhnout PDF s nápovědou( 10MB)

Stáhnout PDF s nápovědou( 10MB) Programování v jazyce Adobe® ActionScript® 3.0 pro aplikaci Adobe® Flash® Pokud je tato příručka distribuovaná se softwarem, ke kterému patří smlouva s koncovým uživatelem, je tato příručka stejně ...

Více