Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Aplikace WinUI, které jsou vytvořeny pomocí sady Windows App SDK a napsány v jazyce C#, využívají automatické správy paměti díky správci paměti .NET. Tento článek shrnuje chování a osvědčené postupy pro optimalizaci výkonu u garbage collectoru .NET v aplikacích WinUI. Další informace o tom, jak funguje garbage collector .NET, a nástrojích pro ladění a analýzu výkonu garbage collectoru naleznete v tématu Uvolňování paměti.
Poznámka:
Nutnost zásahu do výchozího chování uvolňování paměti výrazně značí obecné problémy s pamětí vaší aplikace. Pomocí nástroje Využití paměti ve Visual Studio a doporučení v Garbage Collection a výkon identifikujte objekty, které přežijí sběry.
Garbage Collector určuje, kdy se má spustit, vyvažováním spotřeby paměti spravované haldy s množstvím práce, kterou musí provést. Jedním ze způsobů, jak to garbage collector (GC) provádí, je rozdělení haldy do generací a provedení sběru pouze části haldy po většinu času. Ve spravované haldě existují tři generace:
- Generace 0. Tato generace obsahuje nově přidělené objekty, pokud nejsou 85 kB nebo větší; v takovém případě jsou součástí haldy velkých objektů. Halda velkých objektů je sbírána s kolekcemi generace 2. Kolekce generace 0 jsou nejčastěji se vyskytujícím typem kolekce a vyčistí krátce žijící objekty, jako jsou místní proměnné.
- Generace 1. Tato generace obsahuje objekty, které přežily kolekce 0. generace. Slouží jako vyrovnávací paměť mezi generací 0 a generací 2. Kolekce 1. generace se vyskytují méně často než kolekce 0. generace a odstraňují dočasné objekty, které byly aktivní během předešlých kolekcí 0. generace. Kolekce generace 1 také shromažďuje generaci 0.
- Generace 2. Tato generace obsahuje dlouhožijící objekty, které přežily kolekce generace 0 a generace 1. Kolekce generace 2 jsou nejméně časté a shromažďují celou spravovanou haldu, včetně velké haldy objektů, která obsahuje objekty, které jsou 85 kB nebo větší.
Výkon uvolňování paměti můžete měřit ve dvou aspektech: doba potřebnou k uvolnění paměti a spotřeba paměti spravované haldy. Pokud máte malou aplikaci s velikostí haldy menší než 100 MB, zaměřte se na snížení spotřeby paměti. Pokud máte aplikaci se spravovanou haldou větší než 100 MB, zaměřte se pouze na snížení doby uvolňování paměti. Tady je postup, jak pomoct systému .NET pro správu paměti dosáhnout lepšího výkonu.
Snížení spotřeby paměti
Reference k vydáním
Odkaz na objekt v aplikaci zabrání shromažďování tohoto objektu a všech objektů, na které odkazuje. Kompilátor .NET provádí dobrou úlohu zjišťování, kdy se proměnná už nepoužívá, takže objekty uchovávané danou proměnnou budou způsobilé pro kolekci. V některých případech ale nemusí být zřejmé, že některé objekty mají odkaz na jiné objekty, protože část grafu objektů může vlastnit knihovny, které vaše aplikace používá. Chcete-li se dozvědět o nástrojích a technikách, které umožňují zjistit, které objekty přežijí proces uvolňování paměti, podívejte se na Uvolňování paměti a výkon.
Vyvolejte uvolnění paměti, pokud je to užitečné.
Vyvolejte uvolňování paměti teprve poté, co změříte výkon vaší aplikace a zjistíte, že vynucení kolekce zlepší její výkon.
Uvolňování paměti pro určitou generaci můžete vyvolat voláním GC.Collect(n), kde n je generace, kterou chcete uvolnit (0, 1 nebo 2).
Poznámka:
Doporučujeme nenutit uvolňování paměti ve vaší aplikaci, protože uvolňování paměti využívá mnoho heuristik k určení nejlepší doby pro provedení sběru a vynucení sběru je v mnoha případech zbytečné použití procesoru. Pokud ale víte, že máte v aplikaci velký počet objektů, které se už nepoužívají a chcete vrátit tuto paměť do systému, může být vhodné vynutit garbage collection. Můžete například vyvolat kolekci na konci sekvence načítání ve hře, aby se uvolnila paměť před zahájením hry. Chcete-li zabránit neúmyslnému způsobení příliš mnoha garbage collection, můžete nastavit GCCollectionMode na Optimalizováno. To dává systému uvolňování paměti pokyn, aby spustil kolekci pouze v případě, že zjistí, že by kolekce byla dostatečně produktivní, aby byla odůvodněná.
Zkrácení doby garbage collectionu
Tato část platí, pokud jste analyzovali svou aplikaci a zaznamenali dlouhé doby uvolňování paměti. Mezi doby pozastavení související s uvolňováním paměti patří doba potřebnou ke spuštění jednoho průchodu uvolňování paměti a celkový čas, kdy vaše aplikace stráví uvolňováním paměti. Doba trvání shromažďování závisí na tom, kolik živých dat musí kolektor analyzovat. Generace 0 a generace 1 jsou svázané s velikostí, ale generace 2 stále roste, protože ve vaší aplikaci jsou aktivní více dlouhodobých objektů. To znamená, že časy kolekce pro generaci 0 a 1 jsou vázané, zatímco 2. generace může trvat déle. Jak často probíhá uvolňování paměti, závisí většinou na tom, kolik paměti přidělíte, protože uvolňování paměti tak uvolní paměť, aby uspokojilo požadavky na přidělení.
Uvolňování paměti občas pozastaví vaši aplikaci kvůli provedení úkolů, ale nemusí ji pozastavit po celou dobu, kdy provádí sběr. Časy pozastavení obvykle nejsou v aplikaci srozumitelné pro uživatele, zejména pro kolekce 0. generace a 1. generace. Funkce uvolňování paměti na pozadí systému uvolňování paměti .NET umožňuje, aby se kolekce generace 2 prováděly souběžně, když je vaše aplikace spuštěná, a pozastaví ji jen na krátkou dobu. Není ale vždy možné provést kolekci 2. generace jako kolekci na pozadí. V takovém případě může být pozastavení uživatelem srozumitelné, pokud máte dostatečnou haldu (více než 100 MB).
Časté uvolňování paměti může přispět ke zvýšení zátěže CPU, zvýšení spotřeby energie, delší době načítání nebo snížení snímkové frekvence ve vaší aplikaci. Níže jsou uvedeny některé techniky, které můžete použít ke snížení doby garbage collection a pozastavení souvisejících s garbage collection ve vaší spravované aplikaci WinUI.
Snížit počet alokací paměti
Pokud nepřidělíte žádné objekty, systém uvolňování paměti se nespustí, pokud v systému není nedostatek paměti. Snížení množství paměti, kterou přímo přidělíte, vede k méně častým procesům sběru odpadků.
Pokud jsou v některých částech vaší aplikace zpoždění zcela nežádoucí, můžete potřebné objekty předem přidělit během doby, kdy není výkon kritický. Například hra může přidělit všechny objekty potřebné pro hraní během načítání obrazovky úrovně a během hraní již nepřidělovat žádné objekty. Tím se zabrání pozastavení, když uživatel hraje hru a může mít za následek vyšší a konzistentnější přenosovou frekvenci.
Snižte počet kolekcí generace 2 tím, že se vyhnete objektům s životností střední délky.
Generační garbage kolekce fungují nejlépe, když máte ve své aplikaci opravdu krátkodobé nebo opravdu dlouhodobé objekty. Krátkodobé objekty se sbírají v levnějších kolekcích generace 0 a generace 1, a objekty, které jsou dlouhodobé, jsou povýšeny do generace 2, která se sbírá zřídka. Dlouhodobé objekty jsou objekty, které se používají po celou dobu trvání aplikace nebo během významného období aplikace, například během konkrétní stránky nebo herní úrovně.
Pokud často vytváříte objekty, které mají dočasnou životnost, ale žijí dostatečně dlouho, aby byly povýšeny na generaci 2, pak dochází k častějším a nákladnějším sběrům generace 2. Kolekce 2. generace můžete snížit recyklací existujících objektů nebo rychlejším uvolněním objektů.
Běžným příkladem objektů se střední životností jsou objekty, které se používají k zobrazení položek v seznamu, který uživatel prochází. Pokud se objekty vytvoří, když se položky v seznamu posunou do zobrazení a přestanou být referencovány, když se zobrazení opustí, pak má vaše aplikace obvykle velký počet kolekcí generace 2. V takových situacích můžete předem přidělit a znovu použít sadu objektů pro data aktivně zobrazovaná uživateli a použít krátkodobé objekty pro načítání informací, jakmile se položky v seznamu objeví.
Snižte počet kolekcí generace 2 tím, že se vyhnete velkým objektům s krátkými životnostmi.
Objekty o velikosti 85 kB nebo větší se přidělují na haldu velkých objektů (LOH) a shromažďují se během generace 2. Pokud máte dočasné proměnné, jako jsou vyrovnávací paměti, které jsou větší než 85 kB, kolekce generace 2 je vyčistí. Omezení dočasných proměnných na méně než 85 kB snižuje počet kolekcí generace 2 ve vaší aplikaci. Jednou z běžných technik je vytvoření fondu vyrovnávací paměti a opakované použití objektů z fondu, aby nedocházelo k velkým dočasným přidělením.
Vyhněte se objektům bohatým na reference
Správce paměti určuje, které objekty jsou živé, sledováním odkazů mezi objekty, začínajíc kořeny ve vaší aplikaci. V tématu Co se stane během uvolňování paměti najdete další informace. Pokud objekt obsahuje mnoho odkazů, má uvolňovač paměti více práce. Běžnou technikou, zejména u velkých objektů, je transformování objektů bohatých na odkazy na objekty bez odkazů. Například místo uložení odkazu uložte index. Samozřejmě tato technika funguje pouze v případě, že je to logicky možné provést.
Nahrazení odkazů na objekty indexy může být rušivou a složitou změnou vaší aplikace a je nejúčinnější pro velké objekty s velkým počtem odkazů. Tuto akci proveďte pouze v případě, že ve své aplikaci zjistíte velké časy uvolňování paměti související s objekty náročnými na odkazy.
Windows developer