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
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...
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ě ...