Szemétgyűjtés és teljesítmény
Ez a cikk a szemétgyűjtéssel és a memóriahasználattal kapcsolatos problémákat ismerteti. Foglalkozik a felügyelt halommal kapcsolatos problémákkal, és elmagyarázza, hogyan minimalizálható a szemétgyűjtés hatása az alkalmazásokra. Minden probléma olyan eljárásokra mutató hivatkozásokkal rendelkezik, amelyekkel kivizsgálhatja a problémákat.
Teljesítményelemzési eszközök
A következő szakaszok ismertetik a memóriahasználattal és a szemétgyűjtési problémákkal kapcsolatos problémák kivizsgálására rendelkezésre álló eszközöket. A cikk későbbi részében ismertetett eljárások ezekre az eszközökre vonatkoznak.
Memóriateljesítmény-számlálók
Teljesítményszámlálókkal teljesítményadatokat gyűjthet. Útmutatásért lásd : Runtime Profiling. A teljesítményszámlálók .NET CLR memóriakategóriája a .NET teljesítményszámlálóiban leírtak szerint információt nyújt a szemétgyűjtőről.
Hibakeresés az SOS használatával
A Windows Hibakereső (WinDbg) használatával megvizsgálhatja a felügyelt halom objektumait.
A WinDbg telepítéséhez telepítse a Windows hibakeresési eszközeit a Windowshoz készült hibakeresési eszközök letöltési oldaláról.
Szemétgyűjtési ETW-események
A Windows eseménykövetése (ETW) egy nyomkövetési rendszer, amely kiegészíti a .NET által biztosított profilkészítési és hibakeresési támogatást. A 4. .NET-keretrendszer kezdve a szemétgyűjtési ETW-események hasznos információkat rögzítenek a felügyelt halom statisztikai szempontból történő elemzéséhez. A szemétgyűjtés során létrejönő esemény például GCStart_V1
a következő információkat adja meg:
- Az objektumok melyik generációját gyűjti össze a rendszer.
- Mi váltotta ki a szemétgyűjtést.
- A szemétgyűjtés típusa (egyidejű vagy nem egyidejű).
Az ETW eseménynaplózása hatékony, és nem fedi el a szemétgyűjtéssel kapcsolatos teljesítményproblémát. A folyamat képes saját eseményeket biztosítani az ETW-eseményekkel együtt. Naplózva az alkalmazás eseményei és a szemétgyűjtési események korrelálhatók annak meghatározásához, hogy hogyan és mikor fordulnak elő halomproblémák. Egy kiszolgálóalkalmazás például eseményeket biztosíthat egy ügyfélkérés elején és végén.
A Profilkészítési API
A közös nyelvi futtatókörnyezet (CLR) profilkészítési felületei részletes információkat nyújtanak a szemétgyűjtés során érintett objektumokról. A profilkészítők értesítést kaphatnak a szemétgyűjtés elindulásáról és befejezéséről. Jelentéseket tud nyújtani a felügyelt halom objektumairól, beleértve az egyes generációk objektumainak azonosítását is. További információ: Profilkészítés áttekintése.
A profilkészítők átfogó információkat nyújthatnak. Az összetett profilkészítők azonban módosíthatják az alkalmazások viselkedését.
Alkalmazástartomány erőforrás-monitorozása
A 4. .NET-keretrendszer kezdve az alkalmazástartomány erőforrás-monitorozása (ARM) lehetővé teszi, hogy a gazdagépek alkalmazástartományonként monitorozzák a processzor- és memóriahasználatot. További információ: Application Domain Resource Monitoring.
Teljesítményproblémák elhárítása
Az első lépés annak meghatározása, hogy a probléma valójában szemétgyűjtés-e. Ha azt állapítja meg, hogy igen, válassza az alábbi listából a probléma elhárításához.
- A rendszer memóriakivételt jelez
- A folyamat túl sok memóriát használ
- A szemétgyűjtő nem gyűjti vissza elég gyorsan az objektumokat
- A felügyelt halom túl töredezett
- A szemétgyűjtési szünetek túl hosszúak
- A 0. generáció túl nagy
- Túl magas a processzorhasználat a szemétgyűjtés során
Probléma: Memóriakivétel van kibocsátva
A felügyeltek OutOfMemoryException esetében két jogos eset áll fenn:
Elfogy a virtuális memória.
A szemétgyűjtő előre meghatározott méretű szegmensekben foglalja le a memóriát a rendszerből. Ha egy foglaláshoz további szegmensre van szükség, de a folyamat virtuális memóriájában nincs egybefüggő szabad blokk, a felügyelt halom lefoglalása sikertelen lesz.
Nincs elég fizikai memória a lefoglaláshoz.
Teljesítményellenőrzések |
---|
Határozza meg, hogy a memóriakivétel felügyelt-e. Határozza meg, hogy mennyi virtuális memória foglalható le. Határozza meg, hogy van-e elegendő fizikai memória. |
Ha úgy ítéli meg, hogy a kivétel nem jogszerű, forduljon a Microsoft ügyfélszolgálatához az alábbi információkkal:
- A felügyelt memóriakivétellel rendelkező verem.
- Teljes memóriakép.
- Azok az adatok, amelyek igazolják, hogy ez nem memóriakivétel, beleértve azokat az adatokat is, amelyek azt mutatják, hogy a virtuális vagy a fizikai memória nem jelent problémát.
Probléma: A folyamat túl sok memóriát használ
Gyakori feltételezés, hogy a Windows Feladatkezelő Teljesítmény lapján megjelenő memóriahasználat jelezheti, ha túl sok memória van használatban. Ez a megjelenítés azonban a munkakészletre vonatkozik; nem ad meg információt a virtuális memória használatáról.
Ha megállapítja, hogy a problémát a felügyelt halom okozza, a minták meghatározásához meg kell mérnie a felügyelt halomot.
Ha megállapítja, hogy a problémát nem a felügyelt halom okozza, natív hibakeresést kell használnia.
Probléma: A szemétgyűjtő nem vonja vissza elég gyorsan az objektumokat
Ha úgy tűnik, hogy az objektumok nem a várt módon lesznek visszakövetelve a szemétgyűjtéshez, meg kell állapítania, hogy vannak-e erős hivatkozások ezekre az objektumokra.
Ezt a problémát akkor is tapasztalhatja, ha nem történt szemétgyűjtés a halott objektumot tartalmazó generáció számára, ami azt jelzi, hogy a halott objektum véglegesítője nem lett futtatva. Ez például akkor lehetséges, ha egyszálas lakásalkalmazást (STA) futtat, és a véglegesítő üzenetsort kiszolgáló szál nem hívható be.
Teljesítményellenőrzések |
---|
Ellenőrizze az objektumokra mutató hivatkozásokat. Annak megállapítása, hogy a véglegesítő futtatva van-e. Határozza meg, hogy vannak-e véglegesítésre váró objektumok. |
Probléma: A felügyelt halom túl töredezett
A töredezettségi szintet a rendszer a szabad terület és a teljes lefoglalt memória arányával számítja ki a generáció számára. A 2. generáció esetében a töredezettség elfogadható szintje legfeljebb 20%. Mivel a 2. generáció nagyon nagy lehet, a töredezettség aránya fontosabb, mint az abszolút érték.
A 0. generációs szabad terület használata nem jelent problémát, mert ez az a generáció, ahol új objektumok vannak lefoglalva.
A töredezettség mindig a nagy objektum halomban fordul elő, mert nem tömöríti. A szomszédos szabad objektumok természetesen egyetlen térbe vannak összecsukva a nagy méretű objektumfoglalási kérelmek kielégítése érdekében.
A töredezettség problémát okozhat az 1. és a 2. generációban. Ha ezek a generációk nagy mennyiségű szabad területtel rendelkeznek a szemétgyűjtés után, előfordulhat, hogy az alkalmazás objektumhasználata módosításra szorul, és érdemes megfontolni a hosszú távú objektumok élettartamának újraértékelését.
Az objektumok túlzott rögzítése növelheti a töredezettségeket. Ha a töredezettség magas, túl sok objektum rögzíthető.
Ha a virtuális memória töredezettsége megakadályozza, hogy a szemétgyűjtő szegmenseket adjon hozzá, az okok a következők lehetnek:
Sok kis szerelvények gyakori be- és kirakodása.
Ha nem felügyelt kóddal működik, túl sok hivatkozás van a COM-objektumokra.
Nagy átmeneti objektumok létrehozása, amelyek miatt a nagy objektum halom gyakran foglal le és szabadít fel halomszegmenseket.
A CLR üzemeltetése során egy alkalmazás kérheti, hogy a szemétgyűjtő megtartsa a szegmenseit. Ez csökkenti a szegmensfoglalások gyakoriságát. Ezt a STARTUP_FLAGS Enumerálás STARTUP_HOARD_GC_VM jelölőjének használatával lehet elvégezni.
Teljesítményellenőrzések |
---|
Határozza meg a felügyelt halom szabad területének mennyiségét. Határozza meg a rögzített objektumok számát. |
Ha úgy véli, hogy a töredezettségnek nincs jogos oka, forduljon a Microsoft ügyfélszolgálatához és ügyfélszolgálatához.
Probléma: A szemétgyűjtés szüneteltetése túl hosszú
A szemétgyűjtés valós időben működik, ezért az alkalmazásnak képesnek kell lennie némi szünetet elviselni. A helyreállítható valós idejű műveletek egyik feltétele, hogy a műveletek 95%-ának időben kell befejeződnie.
Egyidejű szemétgyűjtés esetén a felügyelt szálak futtathatók a gyűjtemény során, ami azt jelenti, hogy a szüneteltetések nagyon minimálisak.
A rövid ideig tartó szemétgyűjtés (0. és 1. generáció) csak néhány ezredmásodpercig tart, ezért a szüneteltetések csökkentése általában nem megvalósítható. A 2. generációs gyűjtemények szüneteit azonban csökkentheti úgy, hogy módosítja az alkalmazás általi foglalási kérelmek mintáját.
Egy másik, pontosabb módszer a szemétgyűjtési ETW-események használata. A gyűjtemények időzítését úgy találja meg, hogy hozzáadja az események sorozatához tartozó időbélyeg-különbségeket. A teljes gyűjteménysorozat magában foglalja a végrehajtó motor felfüggesztését, magát a szemétgyűjtést és a végrehajtó motor újraindítását.
A Szemétgyűjtési értesítések segítségével megállapíthatja, hogy egy kiszolgáló 2. generációs gyűjteményt fog-e használni, és hogy a kérések másik kiszolgálóra való átirányítása enyhítheti-e a szüneteltetésekkel kapcsolatos problémákat.
Teljesítményellenőrzések |
---|
Határozza meg a szemétgyűjtés időtartamát. Határozza meg, hogy mi okozta a szemétgyűjtést. |
Probléma: A 0. generáció túl nagy
A 0. generáció valószínűleg nagyobb számú objektummal rendelkezik egy 64 bites rendszeren, különösen akkor, ha a munkaállomás szemétgyűjtése helyett kiszolgálói szemétgyűjtést használ. Ennek az az oka, hogy a 0. generációs szemétgyűjtés aktiválásának küszöbértéke magasabb ezekben a környezetekben, és a 0. generációs gyűjtemények sokkal nagyobbak lehetnek. A teljesítmény akkor javul, ha egy alkalmazás több memóriát foglal le a szemétgyűjtés aktiválása előtt.
Probléma: A processzorhasználat a szemétgyűjtés során túl magas
A cpu-használat magas lesz a szemétgyűjtés során. Ha jelentős mennyiségű folyamatidőt töltenek egy szemétgyűjtésben, a gyűjtemények száma túl gyakori, vagy a gyűjtemény túl hosszú ideig tart. A felügyelt halom objektumainak megnövekedett foglalási aránya miatt gyakrabban fordul elő szemétgyűjtés. A foglalási arány csökkentése csökkenti a szemétgyűjtés gyakoriságát.
A foglalási arányokat a Allocated Bytes/second
teljesítményszámlálóval figyelheti. További információ: Teljesítményszámlálók a .NET-ben.
A gyűjtemény időtartama elsősorban azon objektumok számának tényezője, amelyek a lefoglalás után is megmaradnak. A szemétgyűjtőnek nagy mennyiségű memórián kell átmennie, ha sok objektumot kell összegyűjteni. A túlélők tömörítése időigényes munka. Annak megállapításához, hogy hány objektumot kezeltek a gyűjtemény során, állítson be töréspontot a hibakeresőben egy adott generáció szemétgyűjtésének végén.
Teljesítményellenőrzések |
---|
Állapítsa meg, hogy a magas processzorhasználatot a szemétgyűjtés okozza-e. Állítson be egy töréspontot a szemétgyűjtés végén. |
Hibaelhárítási irányelvek
Ez a szakasz azokat az irányelveket ismerteti, amelyeket érdemes megfontolnia a vizsgálatok megkezdésekor.
Munkaállomás vagy kiszolgáló szemétgyűjtése
Állapítsa meg, hogy a megfelelő típusú szemétgyűjtést használja-e. Ha az alkalmazás több szálat és objektumpéldányt használ, a munkaállomás szemétgyűjtése helyett használjon kiszolgálói szemétgyűjtést. A kiszolgálói szemétgyűjtés több szálon működik, míg a munkaállomás szemétgyűjtéséhez több alkalmazáspéldányra van szükség a saját szemétgyűjtési szálak futtatásához és a processzoridőért való versengéshez.
Az alacsony terhelésű és a háttérben ritkán elvégzendő feladatokat (például egy szolgáltatást) használó alkalmazások használhatják a munkaállomás szemétgyűjtését, ha az egyidejű szemétgyűjtés le van tiltva.
Mikor kell mérni a felügyelt halomméretet?
Ha nem használ profilkészítőt, konzisztens mérési mintát kell létrehoznia a teljesítményproblémák hatékony diagnosztizálásához. Az ütemezés kialakításához vegye figyelembe az alábbi szempontokat:
- Ha a 2. generációs szemétgyűjtés után mér, a teljes felügyelt halom szemétmentes lesz (holt objektumok).
- Ha közvetlenül a 0. generációs szemétgyűjtés után mér, az 1. és a 2. generáció objektumai még nem lesznek összegyűjtve.
- Ha közvetlenül a szemétgyűjtés előtt mér, a lehető legtöbb lefoglalást fogja mérni a szemétgyűjtés megkezdése előtt.
- A szemétgyűjtés során történő mérés problematikus, mert a szemétgyűjtő adatstruktúrái nincsenek érvényes állapotban a bejáráshoz, és nem biztos, hogy teljes eredményt adnak. Ez az elvárt működés.
- Ha a munkaállomás szemétgyűjtését egyidejű szemétgyűjtéssel használja, a visszanyert objektumok nem lesznek tömörítve, így a halom mérete azonos vagy nagyobb lehet (a töredezettség nagyobbnak tűnhet).
- A 2. generáció egyidejű szemétgyűjtése késik, ha a fizikai memória terhelése túl magas.
Az alábbi eljárás bemutatja, hogyan állíthat be töréspontot a felügyelt halom méréséhez.
Töréspont beállítása a szemétgyűjtés végén
Az SOS hibakereső bővítményt tartalmazó WinDbg-ben adja meg a következő parancsot:
bp mscorwks!WKS::GCHeap::RestartEE "j (dwo(mscorwks!WKS::GCHeap::GcCondemnedGeneration)==2) 'kb';'g'"
Állítsa a
GcCondemnedGeneration
kívánt generációra. Ehhez a parancshoz privát szimbólumok szükségesek.Ez a parancs megszakítja
RestartEE
a 2. generációs objektumok szemétgyűjtéshez való visszaigénylését.A kiszolgáló szemétgyűjtésében csak egy szál hívja meg a szálakat
RestartEE
, így a töréspont csak egyszer fordul elő a 2. generációs szemétgyűjtés során.
Teljesítményellenőrzési eljárások
Ez a szakasz a teljesítményproblémák okának elkülönítésére vonatkozó alábbi eljárásokat ismerteti:
- Állapítsa meg, hogy a problémát a szemétgyűjtés okozza-e.
- Határozza meg, hogy a memóriakivétel felügyelt-e.
- Határozza meg, hogy mennyi virtuális memória foglalható le.
- Határozza meg, hogy van-e elegendő fizikai memória.
- Határozza meg, hogy a felügyelt halom mekkora memóriát véglegesítse.
- Határozza meg, hogy a felügyelt halom mennyi memóriát foglal le.
- Nagy objektumok meghatározása a 2. generációban.
- Objektumokra mutató hivatkozások meghatározása.
- Annak megállapítása, hogy a véglegesítő futtatva van-e.
- Határozza meg, hogy vannak-e véglegesítésre váró objektumok.
- Határozza meg a felügyelt halom szabad területének mennyiségét.
- Határozza meg a rögzített objektumok számát.
- Határozza meg a szemétgyűjtés időtartamát.
- Határozza meg, mi váltott ki szemétgyűjtést.
- Annak meghatározása, hogy a magas processzorhasználatot a szemétgyűjtés okozza-e.
Annak megállapítása, hogy a problémát a szemétgyűjtés okozza-e
Vizsgálja meg a következő két memóriateljesítmény-számlálót:
%Time in GC. Megjeleníti a legutóbbi szemétgyűjtési ciklus után a szemétgyűjtés végrehajtásával töltött eltelt idő százalékos arányát. Ezzel a számlálóval megállapíthatja, hogy a szemétgyűjtő túl sok időt tölt-e a felügyelt halomterület rendelkezésre állásához. Ha a szemétgyűjtésben töltött idő viszonylag alacsony, az erőforrás-problémát jelezhet a felügyelt halomon kívül. Előfordulhat, hogy ez a számláló nem pontos, ha egyidejű vagy háttérbeli szemétgyűjtésről van szó.
# Véglegesített bájtok száma. Megjeleníti a szemétgyűjtő által jelenleg lekötött virtuális memória mennyiségét. Ezzel a számlálóval megállapíthatja, hogy a szemétgyűjtő által felhasznált memória a memória túlzott része-e, amelyet az alkalmazás használ.
A memóriateljesítmény-számlálók többsége az egyes szemétgyűjtések végén frissül. Ezért előfordulhat, hogy ezek nem tükrözik azokat a jelenlegi feltételeket, amelyekről információt szeretne kapni.
Annak meghatározása, hogy a memóriakivétel kezelése történik-e
Az SOS hibakeresőbővítménnyel rendelkező WinDbg vagy Visual Studio hibakeresőben adja meg a nyomtatási kivétel (
pe
) parancsot:!pe
Ha a kivétel kezelése történik, OutOfMemoryException akkor a rendszer kivételtípusként jelenik meg, ahogyan az alábbi példában is látható.
Exception object: 39594518 Exception type: System.OutOfMemoryException Message: <none> InnerException: <none> StackTrace (generated):
Ha a kimenet nem ad meg kivételt, meg kell határoznia, hogy melyik szálból származik a memóriakivétel. Adja meg a következő parancsot a hibakeresőben az összes szál megjelenítéséhez a hívásveremekkel:
~\*kb
A kivételhívásokat tartalmazó vermet tartalmazó szálat az
RaiseTheException
argumentum jelöli. Ez a felügyelt kivételobjektum.28adfb44 7923918f 5b61f2b4 00000000 5b61f2b4 mscorwks!RaiseTheException+0xa0
A beágyazott kivételeket az alábbi paranccsal teheti ki.
!pe -nested
Ha nem talál kivételeket, a memóriakivétel nem felügyelt kódból származik.
Annak meghatározása, hogy mennyi virtuális memória foglalható le
Az SOS hibakereső bővítményt tartalmazó WinDbg-ben adja meg a következő parancsot a legnagyobb ingyenes régió lekéréséhez:
!address -summary
A legnagyobb szabad régió az alábbi kimenetben látható módon jelenik meg.
Largest free region: Base 54000000 - Size 0003A980
Ebben a példában a legnagyobb szabad régió mérete körülbelül 24000 KB (hexadecimális 3A980). Ez a régió sokkal kisebb, mint amire a szemétgyűjtőnek szüksége van egy szegmenshez.
-Vagy-
Használja a
vmstat
következő parancsot:!vmstat
A legnagyobb szabad régió a LEGNAGYOBB oszlop legnagyobb értéke, ahogy az az alábbi kimenetben is látható.
TYPE MINIMUM MAXIMUM AVERAGE BLK COUNT TOTAL ~~~~ ~~~~~~~ ~~~~~~~ ~~~~~~~ ~~~~~~~~~~ ~~~~ Free: Small 8K 64K 46K 36 1,671K Medium 80K 864K 349K 3 1,047K Large 1,384K 1,278,848K 151,834K 12 1,822,015K Summary 8K 1,278,848K 35,779K 51 1,824,735K
Annak meghatározása, hogy van-e elegendő fizikai memória
Indítsa el a Windows Feladatkezelőt.
Performance
A lapon tekintse meg a véglegesített értéket. (A Windows 7-ben tekintseCommit (KB)
meg aSystem group
.)Ha a
Total
rendszer a közelbenLimit
van, akkor kevés a fizikai memória.
Annak meghatározása, hogy a felügyelt halom mennyi memóriát véglegesített
# Total committed bytes
A memóriateljesítmény-számlálóval lekérheti a felügyelt halom által véglegesített bájtok számát. A szemétgyűjtő szükség szerint véglegesíti az adattömböket egy szegmensen, nem egyszerre.Feljegyzés
Ne használja a
# Bytes in all Heaps
teljesítményszámlálót, mert nem a felügyelt halom tényleges memóriahasználatát jelöli. Egy generáció mérete ebben az értékben szerepel, és valójában a küszöbértéke, vagyis az a méret, amely szemétgyűjtést indukál, ha a generáció tele van objektumokkal. Ezért ez az érték általában nulla.
Annak meghatározása, hogy a felügyelt halom mennyi memóriát foglal le
Használja a
# Total reserved bytes
memóriateljesítmény-számlálót.A szemétgyűjtő szegmensekben foglalja le a memóriát, és a parancs használatával meghatározhatja, hogy hol kezdődik egy
eeheap
szegmens.Fontos
Bár meghatározhatja, hogy a szemétgyűjtő mennyi memóriát foglal le az egyes szegmensekhez, a szegmens mérete implementációspecifikus, és bármikor változhat, beleértve az időszakos frissítéseket is. Az alkalmazásnak soha nem szabad feltételezéseket feltételeznie egy adott szegmens méretéről vagy attól függenie, és nem is próbálja meg konfigurálni a szegmensfoglalásokhoz rendelkezésre álló memória mennyiségét.
Az SOS hibakereső bővítményt tartalmazó WinDbg- vagy Visual Studio-hibakeresőben adja meg a következő parancsot:
!eeheap -gc
Az eredmény a következő.
Number of GC Heaps: 2 ------------------------------ Heap 0 (002db550) generation 0 starts at 0x02abe29c generation 1 starts at 0x02abdd08 generation 2 starts at 0x02ab0038 ephemeral segment allocation context: none segment begin allocated size 02ab0000 02ab0038 02aceff4 0x0001efbc(126908) Large object heap starts at 0x0aab0038 segment begin allocated size 0aab0000 0aab0038 0aab2278 0x00002240(8768) Heap Size 0x211fc(135676) ------------------------------ Heap 1 (002dc958) generation 0 starts at 0x06ab1bd8 generation 1 starts at 0x06ab1bcc generation 2 starts at 0x06ab0038 ephemeral segment allocation context: none segment begin allocated size 06ab0000 06ab0038 06ab3be4 0x00003bac(15276) Large object heap starts at 0x0cab0038 segment begin allocated size 0cab0000 0cab0038 0cab0048 0x00000010(16) Heap Size 0x3bbc(15292) ------------------------------ GC Heap Size 0x24db8(150968)
A "szegmens" által megjelölt címek a szegmensek kezdőcímei.
Nagy objektumok meghatározása a 2. generációban
Az SOS hibakereső bővítményt tartalmazó WinDbg- vagy Visual Studio-hibakeresőben adja meg a következő parancsot:
!dumpheap –stat
Ha a felügyelt halom nagy,
dumpheap
eltarthat egy ideig.Elkezdheti az elemzést a kimenet utolsó néhány sorából, mert a legtöbb helyet használó objektumokat listázzák. Példa:
2c6108d4 173712 14591808 DevExpress.XtraGrid.Views.Grid.ViewInfo.GridCellInfo 00155f80 533 15216804 Free 7a747c78 791070 15821400 System.Collections.Specialized.ListDictionary+DictionaryNode 7a747bac 700930 19626040 System.Collections.Specialized.ListDictionary 2c64e36c 78644 20762016 DevExpress.XtraEditors.ViewInfo.TextEditViewInfo 79124228 121143 29064120 System.Object[] 035f0ee4 81626 35588936 Toolkit.TlkOrder 00fcae40 6193 44911636 WaveBasedStrategy.Tick_Snap[] 791242ec 40182 90664128 System.Collections.Hashtable+bucket[] 790fa3e0 3154024 137881448 System.String Total 8454945 objects
Az utolsó felsorolt objektum egy sztring, és a legtöbb helyet foglalja el. Megvizsgálhatja az alkalmazást, hogy lássa, hogyan optimalizálhatók a sztringobjektumok. A 150 és 200 bájt közötti sztringek megtekintéséhez írja be a következőket:
!dumpheap -type System.String -min 150 -max 200
Az eredményekre a következő példa látható.
Address MT Size Gen 1875d2c0 790fa3e0 152 2 System.String HighlightNullStyle_Blotter_PendingOrder-11_Blotter_PendingOrder-11 …
Az azonosítók sztring helyett egész szám használata hatékonyabb lehet. Ha ugyanazt a sztringet több ezer alkalommal ismétli meg, fontolja meg a sztringek közötti internálást. A sztringek közötti internálással kapcsolatos további információkért tekintse meg a metódus referenciatémakörét String.Intern .
Objektumokra mutató hivatkozások meghatározása
Az SOS hibakereső bővítményt tartalmazó WinDbg-ben adja meg az alábbi parancsot az objektumokra mutató hivatkozások listázásához:
!gcroot
-Vagy-
Egy adott objektum hivatkozásainak meghatározásához adja meg a címet:
!gcroot 1c37b2ac
A veremeken található gyökerek hamis pozitívak lehetnek. További információkért használja a parancsot
!help gcroot
.ebx:Root:19011c5c(System.Windows.Forms.Application+ThreadContext)-> 19010b78(DemoApp.FormDemoApp)-> 19011158(System.Windows.Forms.PropertyStore)-> … [omitted] 1c3745ec(System.Data.DataTable)-> 1c3747a8(System.Data.DataColumnCollection)-> 1c3747f8(System.Collections.Hashtable)-> 1c376590(System.Collections.Hashtable+bucket[])-> 1c376c98(System.Data.DataColumn)-> 1c37b270(System.Data.Common.DoubleStorage)-> 1c37b2ac(System.Double[]) Scan Thread 0 OSTHread 99c Scan Thread 6 OSTHread 484
A
gcroot
parancs végrehajtása hosszú időt vehet igénybe. A szemétgyűjtés által nem visszanyert objektumok élő objektumok. Ez azt jelenti, hogy néhány gyökér közvetlenül vagy közvetve az objektumhoz kötődik, ezértgcroot
az elérési út adatait vissza kell adnia az objektumnak. Meg kell vizsgálnia a visszaadott gráfokat, és meg kell vizsgálnia, hogy miért hivatkoznak még ezekre az objektumokra.
Annak megállapítása, hogy a véglegesítő futtatása megtörtént-e
Futtasson egy tesztprogramot, amely a következő kódot tartalmazza:
GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect();
Ha a teszt megoldja a problémát, ez azt jelenti, hogy a szemétgyűjtő nem igényelt vissza objektumokat, mert az objektumok véglegesítőit felfüggesztették. A GC.WaitForPendingFinalizers módszer lehetővé teszi, hogy a véglegesítők elvégezzék a feladataikat, és kijavítsák a problémát.
Annak meghatározása, hogy vannak-e véglegesítésre váró objektumok
Az SOS hibakereső bővítményt tartalmazó WinDbg- vagy Visual Studio-hibakeresőben adja meg a következő parancsot:
!finalizequeue
Tekintse meg a véglegesítésre kész objektumok számát. Ha a szám magas, meg kell vizsgálnia, hogy ezek a véglegesítők egyáltalán miért nem tudnak előrehaladni, vagy nem tudnak elég gyorsan haladni.
A szálak kimenetének lekéréséhez írja be a következő parancsot:
!threads -special
Ez a parancs a következőhöz hasonló kimenetet biztosít.
OSID Special thread type 2 cd0 DbgHelper 3 c18 Finalizer 4 df0 GC SuspendEE
A finalizer szál jelzi, hogy melyik véglegesítő fut éppen, ha van ilyen. Ha egy finalizer-szál nem futtat véglegesítőket, az eseményre vár, hogy elmondja neki, hogy végezze el a munkáját. Az idő nagy részében ebben az állapotban fogja látni a finalizer szálat, mert THREAD_HIGHEST_PRIORITY fut, és a véglegesítők futtatását kell befejeznie, ha vannak ilyenek, nagyon gyorsan.
A felügyelt halom szabad területének meghatározása
Az SOS hibakereső bővítményt tartalmazó WinDbg- vagy Visual Studio-hibakeresőben adja meg a következő parancsot:
!dumpheap -type Free -stat
Ez a parancs megjeleníti a felügyelt halom összes szabad objektumának teljes méretét, ahogyan az az alábbi példában is látható.
total 230 objects Statistics: MT Count TotalSize Class Name 00152b18 230 40958584 Free Total 230 objects
A 0. generáció szabad helyének meghatározásához adja meg a következő parancsot a memóriahasználati információk generációnkénti megadásához:
!eeheap -gc
Ez a parancs az alábbihoz hasonló kimenetet jelenít meg. Az utolsó sorban a rövid élettartamú szegmens látható.
Heap 0 (0015ad08) generation 0 starts at 0x49521f8c generation 1 starts at 0x494d7f64 generation 2 starts at 0x007f0038 ephemeral segment allocation context: none segment begin allocated size 00178250 7a80d84c 7a82f1cc 0x00021980(137600) 00161918 78c50e40 78c7056c 0x0001f72c(128812) 007f0000 007f0038 047eed28 0x03ffecf0(67103984) 3a120000 3a120038 3a3e84f8 0x002c84c0(2917568) 46120000 46120038 49e05d04 0x03ce5ccc(63855820)
Számítsa ki a 0. generáció által használt területet:
? 49e05d04-0x49521f8c
Az eredmény a következő. A 0. generáció körülbelül 9 MB.
Evaluate expression: 9321848 = 008e3d78
A következő parancs a 0. generációs tartomány szabad területét adja ki:
!dumpheap -type Free -stat 0x49521f8c 49e05d04
Az eredmény a következő.
------------------------------ Heap 0 total 409 objects ------------------------------ Heap 1 total 0 objects ------------------------------ Heap 2 total 0 objects ------------------------------ Heap 3 total 0 objects ------------------------------ total 409 objects Statistics: MT Count TotalSize Class Name 0015a498 409 7296540 Free Total 409 objects
Ez a kimenet azt mutatja, hogy a halom 0. generációs része 9 MB területet használ az objektumok számára, és 7 MB szabad. Ez az elemzés bemutatja, hogy a 0. generáció milyen mértékben járul hozzá a töredezettséghez. Ezt a halomhasználatot a teljes összegből kell kivenni a hosszú távú objektumok töredezettségének okaként.
Rögzített objektumok számának meghatározása
Az SOS hibakereső bővítményt tartalmazó WinDbg- vagy Visual Studio-hibakeresőben adja meg a következő parancsot:
!gchandles
A megjelenített statisztikák tartalmazzák a rögzített fogópontok számát, ahogy az az alábbi példában is látható.
GC Handle Statistics: Strong Handles: 29 Pinned Handles: 10
A szemétgyűjtés időtartamának meghatározása
Vizsgálja meg a memóriateljesítmény-számlálót
% Time in GC
.Az érték kiszámítása mintaintervallum-idő alapján történik. Mivel a számlálók az egyes szemétgyűjtések végén frissülnek, az aktuális minta értéke megegyezik az előző mintával, ha az intervallum alatt nem történt gyűjtemény.
A gyűjtési idő a mintaintervallum és a százalékos érték szorzatával nyerhető ki.
A következő adatok négy két másodperces mintavételi időközt mutatnak egy 8 másodperces vizsgálathoz. A
Gen0
,Gen1
ésGen2
az oszlopok az adott generációs intervallum végére befejezett szemétgyűjtések teljes számát jelenítik meg.Interval Gen0 Gen1 Gen2 % Time in GC 1 9 3 1 10 2 10 3 1 1 3 11 3 1 3 4 11 3 1 3
Ez az információ nem jeleníti meg, hogy mikor történt a szemétgyűjtés, de meghatározhatja az időintervallumban történt szemétgyűjtések számát. A legrosszabb esetet feltételezve a 0. generációs szemétgyűjtés a második intervallum elején, a 11. generációs 0 szemétgyűjtés pedig a harmadik intervallum végén fejeződött be. A tizedik és a tizenegyedik szemétgyűjtés vége közötti idő körülbelül 2 másodperc, a teljesítményszámláló pedig 3%-ot mutat, így a 11. generációs 0 szemétgyűjtés időtartama (2 másodperc * 3% = 60 ms).
A következő példában öt időköz van.
Interval Gen0 Gen1 Gen2 % Time in GC 1 9 3 1 3 2 10 3 1 1 3 11 4 1 1 4 11 4 1 1 5 11 4 2 20
A második generációs 2 szemétgyűjtés a negyedik intervallumban kezdődött, és az ötödik intervallumban fejeződött be. A legrosszabb esetet feltételezve az utolsó szemétgyűjtés egy 0. generációs gyűjteményre vonatkozik, amely a harmadik intervallum elején fejeződött be, a 2. generációs szemétgyűjtés pedig az ötödik intervallum végén fejeződött be. Ezért a 0. generációs szemétgyűjtés vége és a 2. generációs szemétgyűjtés vége közötti idő 4 másodperc. Mivel a
% Time in GC
számláló 20%, a 2. generációs szemétgyűjtés maximális időtartama (4 másodperc * 20% = 800 ms).Másik lehetőségként meghatározhatja a szemétgyűjtés hosszát a szemétgyűjtés ETW-eseményeinek használatával, és elemezheti az információkat a szemétgyűjtés időtartamának meghatározásához.
Az alábbi adatok például olyan eseményütemezést mutatnak, amely nem egyidejű szemétgyűjtés során történt.
Timestamp Event name 513052 GCSuspendEEBegin_V1 513078 GCSuspendEEEnd 513090 GCStart_V1 517890 GCEnd_V1 517894 GCHeapStats 517897 GCRestartEEBegin 517918 GCRestartEEEnd
A felügyelt szál felfüggesztése 26us (
GCSuspendEEEnd
–GCSuspendEEBegin_V1
) értéket vett igénybe.A tényleges szemétgyűjtés 4,8 m ( –
GCEnd_V1
GCStart_V1
).A felügyelt szálak folytatása 21us (
GCRestartEEEnd
–GCRestartEEBegin
) értéket vett igénybe.Az alábbi kimenet egy példa a háttérbeli szemétgyűjtésre, és tartalmazza a folyamatot, a szálat és az eseménymezőket. (Nem minden adat jelenik meg.)
timestamp(us) event name process thread event field 42504385 GCSuspendEEBegin_V1 Test.exe 4372 1 42504648 GCSuspendEEEnd Test.exe 4372 42504816 GCStart_V1 Test.exe 4372 102019 42504907 GCStart_V1 Test.exe 4372 102020 42514170 GCEnd_V1 Test.exe 4372 42514204 GCHeapStats Test.exe 4372 102020 42832052 GCRestartEEBegin Test.exe 4372 42832136 GCRestartEEEnd Test.exe 4372 63685394 GCSuspendEEBegin_V1 Test.exe 4744 6 63686347 GCSuspendEEEnd Test.exe 4744 63784294 GCRestartEEBegin Test.exe 4744 63784407 GCRestartEEEnd Test.exe 4744 89931423 GCEnd_V1 Test.exe 4372 102019 89931464 GCHeapStats Test.exe 4372
A
GCStart_V1
42504816 esemény azt jelzi, hogy ez egy háttérbeli szemétgyűjtés, mert az utolsó mező.1
Ez lesz a 102019. számú szemétgyűjtés.Az
GCStart
esemény azért fordul elő, mert a háttérbeli szemétgyűjtés megkezdése előtt rövid ideig szükség van a szemétgyűjtésre. Ez lesz a 102020-ra szóló szemétgyűjtés.A 42514170 102020-ra befejeződött a szemétgyűjtés. A felügyelt szálak ezen a ponton újraindulnak. Ez a 4372-s szálon fejeződik be, amely aktiválta ezt a háttérbeli szemétgyűjtést.
A 4744-ben felfüggesztés történik. Ez az egyetlen alkalom, amikor a háttérbeli szemétgyűjtésnek fel kell függesztenie a felügyelt szálakat. Ez az időtartam körülbelül 99 ms ((63784407-63685394)/1000).
A
GCEnd
háttérbeli szemétgyűjtés eseménye 89931423. Ez azt jelenti, hogy a háttérbeli szemétgyűjtés körülbelül 47 másodpercig tartott ((89931423-42504816)/1000).Miközben a felügyelt szálak futnak, tetszőleges számú rövid ideig futó szemétgyűjtés jelenik meg.
Annak meghatározása, hogy mi váltott ki szemétgyűjtést
Az SOS hibakereső bővítményt tartalmazó WinDbg- vagy Visual Studio-hibakeresőben adja meg a következő parancsot a hívásveremekkel rendelkező összes szál megjelenítéséhez:
~*kb
Ez a parancs az alábbihoz hasonló kimenetet jelenít meg.
0012f3b0 79ff0bf8 mscorwks!WKS::GCHeap::GarbageCollect 0012f454 30002894 mscorwks!GCInterface::CollectGeneration+0xa4 0012f490 79fa22bd fragment_ni!request.Main(System.String[])+0x48
Ha a szemétgyűjtést az operációs rendszer alacsony memória-értesítése okozta, a hívásverem hasonló, azzal a különbségtel, hogy a szál a véglegesítő szál. A finalizer szál aszinkron alacsony memória-értesítést kap, és indukálja a szemétgyűjtést.
Ha a szemétgyűjtést memóriafoglalás okozta, a verem a következőképpen jelenik meg:
0012f230 7a07c551 mscorwks!WKS::GCHeap::GarbageCollectGeneration 0012f2b8 7a07cba8 mscorwks!WKS::gc_heap::try_allocate_more_space+0x1a1 0012f2d4 7a07cefb mscorwks!WKS::gc_heap::allocate_more_space+0x18 0012f2f4 7a02a51b mscorwks!WKS::GCHeap::Alloc+0x4b 0012f310 7a02ae4c mscorwks!Alloc+0x60 0012f364 7a030e46 mscorwks!FastAllocatePrimitiveArray+0xbd 0012f424 300027f4 mscorwks!JIT_NewArr1+0x148 000af70f 3000299f fragment_ni!request..ctor(Int32, Single)+0x20c 0000002a 79fa22bd fragment_ni!request.Main(System.String[])+0x153
A just-in-time segítő (
JIT_New*
) végül meghívjaGCHeap::GarbageCollectGeneration
. Ha megállapítja, hogy a 2. generációs szemétgyűjtéseket foglalások okozzák, meg kell határoznia, hogy a 2. generációs szemétgyűjtés mely objektumokat gyűjti össze, és hogyan kerülheti el őket. Ez azt jelzi, hogy mi a különbség a 2. generációs szemétgyűjtés kezdete és vége, valamint a 2. generációs gyűjteményt okozó objektumok között.Írja be például a következő parancsot a hibakeresőbe a 2. generációs gyűjtemény elejének megjelenítéséhez:
!dumpheap –stat
Példakimenet (a legnagyobb helyet használó objektumok rövidített megjelenítése):
79124228 31857 9862328 System.Object[] 035f0384 25668 11601936 Toolkit.TlkPosition 00155f80 21248 12256296 Free 79103b6c 297003 13068132 System.Threading.ReaderWriterLock 7a747ad4 708732 14174640 System.Collections.Specialized.HybridDictionary 7a747c78 786498 15729960 System.Collections.Specialized.ListDictionary+DictionaryNode 7a747bac 700298 19608344 System.Collections.Specialized.ListDictionary 035f0ee4 89192 38887712 Toolkit.TlkOrder 00fcae40 6193 44911636 WaveBasedStrategy.Tick_Snap[] 7912c444 91616 71887080 System.Double[] 791242ec 32451 82462728 System.Collections.Hashtable+bucket[] 790fa3e0 2459154 112128436 System.String Total 6471774 objects
Ismételje meg a parancsot a 2. generáció végén:
!dumpheap –stat
Példakimenet (a legnagyobb helyet használó objektumok rövidített megjelenítése):
79124228 26648 9314256 System.Object[] 035f0384 25668 11601936 Toolkit.TlkPosition 79103b6c 296770 13057880 System.Threading.ReaderWriterLock 7a747ad4 708730 14174600 System.Collections.Specialized.HybridDictionary 7a747c78 786497 15729940 System.Collections.Specialized.ListDictionary+DictionaryNode 7a747bac 700298 19608344 System.Collections.Specialized.ListDictionary 00155f80 13806 34007212 Free 035f0ee4 89187 38885532 Toolkit.TlkOrder 00fcae40 6193 44911636 WaveBasedStrategy.Tick_Snap[] 791242ec 32370 82359768 System.Collections.Hashtable+bucket[] 790fa3e0 2440020 111341808 System.String Total 6417525 objects
Az
double[]
objektumok eltűntek a kimenet végéről, ami azt jelenti, hogy összegyűjtötték őket. Ezek az objektumok körülbelül 70 MB-ot számlálnak. A többi objektum nem sokat változott. Ezért ezek azdouble[]
objektumok voltak az oka ennek a 2. generációs szemétgyűjtésnek. A következő lépés annak meghatározása, hogy miért vannak ott azdouble[]
objektumok, és miért haltak meg. Megkérdezheti a kód fejlesztőjét, hogy honnan származnak ezek az objektumok, vagy használhatja agcroot
parancsot.
Annak megállapítása, hogy a magas processzorhasználatot a szemétgyűjtés okozza-e
Korrelálja a
% Time in GC
memóriateljesítmény-számláló értékét a folyamatidővel.Ha az érték a
% Time in GC
folyamatidővel egy időben emelkedik, a szemétgyűjtés magas processzorhasználatot okoz. Ellenkező esetben profilozza az alkalmazást, hogy megtudja, hol fordul elő a magas kihasználtság.