Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
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 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 profiler értesítést kaphat, amikor a szemétgyűjtés megkezdődik és véget ér. 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
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óriakimerülési kivétel történt
A felügyeltek OutOfMemoryException esetében két jogos eset áll fenn:
A virtuális memória kezd kifogyni.
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.
Nem áll rendelkezésre 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ória dömping
- 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, idővel mérnie kell a felügyelt halom változásait, hogy meghatározza az esetleges mintákat.
Ha megállapítja, hogy a problémát nem a felügyelt kupac okozza, akkor natív hibakeresést kell alkalmaznia.
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 felszabadítva szemétgyűjtés céljából, meg kell állapítani, hogy léteznek-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 apartman (STA) alkalmazást futtat, és a véglegesítő sor kiszolgáló szál nem tud belépni abba.
| 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 előfordul a nagy objektumkupacban, mivel az nincs tömörítve. 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. Amennyiben a töredezettség magas, túl sok objektum rögzítve lehetett.
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 alkatrész 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 szegmenseket foglal le és szabadít fel.
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_HOARD_GC_VM jelző használatával hajtják végre a STARTUP_FLAGS Enumerációban.
| 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.
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 lágy valós idejű műveletek egyik feltétele, hogy a műveletek 95%-a időben fejeződjön be.
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 kezelt kupacmé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 művelet után mér, a teljes kezelési halom szemétmentes lesz (hasznavehetetlen 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 szándékosan van így.
- 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 leírja, hogyan lehet beállítani egy töréspontot a kezelt 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
GcCondemnedGenerationkívánt generációra. Ehhez a parancshoz privát szimbólumok szükségesek.Ez a parancs sorköz beillesztésére kényszerít, ha a 2. generációs objektumok visszaigénylésre kerültek szemétgyűjtés céljából, és ezt követően hajtják végre a
RestartEEparancsot.A szerver szemétgyűjtésében csak egy szál hívja meg
RestartEE, így a töréspont csak egyszer fordul elő a 2-es generációjú 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 mennyit memóriát köt le a kiszolgált terület.
- 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:
% GC-ben töltött idő. 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ő kiterjesztéssel rendelkező WinDbg vagy Visual Studio hibakeresőben írja be a kivétel nyomtatása (
pe) parancsot.!peHa a kivételt kezelik, OutOfMemoryException 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. A következő parancs megadásával a hibakeresőben megjeleníthetjük az összes szálat és azok hívási veremeit.
~\*kbA kivételhívásokat tartalmazó vermet tartalmazó szálat az
RaiseTheExceptionargumentum jelöli. Ez a felügyelt kivételobjektum.28adfb44 7923918f 5b61f2b4 00000000 5b61f2b4 mscorwks!RaiseTheException+0xa0A beágyazott kivételeket az alábbi paranccsal teheti ki.
!pe -nestedHa 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 -summaryA legnagyobb szabad régió az alábbi kimenetben látható módon jelenik meg.
Largest free region: Base 54000000 - Size 0003A980Ebben 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
vmstatparancsot:!vmstatA 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.
Performancefülön tekintse meg a lefoglalt értéket. (A Windows 7-ben nézze megCommit (KB)aSystem group.)Ha a
Totalközel van aLimit-hez, akkor kevés a fizikai memória.
Annak meghatározása, hogy a felügyelt kupac mennyi memóriát foglal
A
# Total committed bytesmemóriateljesítmény-számlálóval lekérheti a felügyelt halom által lefoglalt bájtok számát. A szemétgyűjtő szükség szerint véglegesíti az adattömböket egy szegmensen, nem egyszerre.Megjegyzés:
Ne használja a
# Bytes in all Heapsteljesí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 bytesmemó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
eeheapszegmens.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 -gcAz 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 –statHa a felügyelt halom nagy,
dumpheapbeletelhet egy kis időbe.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éldául:
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 objectsAz utolsó felsorolt objektum egy karakterlánc, é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 200Az 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 karaktersorozatot több ezer alkalommal ismétli meg, vegye fontolóra a karaktersorozatok tárolási optimalizálását. A sztringek internálásáról szóló további információkért tekintse meg a String.Intern módszer referenciatémakörét.
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 1c37b2acA 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 484A
gcrootparancs 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értgcrootaz 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:
!finalizequeueTekintse 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 -specialEz a parancs a következőhöz hasonló kimenetet biztosít.
OSID Special thread type 2 cd0 DbgHelper 3 c18 Finalizer 4 df0 GC SuspendEEA finalizer szál jelzi, hogy melyik véglegesítő fut éppen, ha van ilyen. Amikor egy finalizáló szál nem futtat véglegesítőket, egy esemény jelzésére vár, hogy elvégezze a feladatát. Az idő nagy részében ebben az állapotban fogja látni a finalizer szálat, mert a THREAD_HIGHEST_PRIORITY prioritással fut, és a véglegesítők futtatását kell nagyon gyorsan befejeznie, ha vannak ilyenek.
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 -statEz 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 objectsA 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 -gcEz 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-0x49521f8cAz eredmény a következő. A 0. generáció körülbelül 9 MB.
Evaluate expression: 9321848 = 008e3d78A következő parancs a 0. generációs tartomány szabad területét adja ki:
!dumpheap -type Free -stat 0x49521f8c 49e05d04Az 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 objectsEz 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 le kell vonni a teljes összegből, mivel a hosszú távú objektumok okozta töredezettséghez köthető.
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:
!gchandlesA 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ésGen2az 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 3Ez 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%, tehát a 0. generációs 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 20A 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 GCszámláló 20%, a 2. generációs szelektív gyűjtés maximális időtartama lehetett volna (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 GCRestartEEEndA felügyelt szál felfüggesztése 26us (
GCSuspendEEEnd–GCSuspendEEBegin_V1) tartott.A tényleges szemétgyűjtés 4,8 ms (
GCEnd_V1–GCStart_V1).A felügyelt szálak folytatása 21 mikrosekundumig tartott (
GCRestartEEEnd–GCRestartEEBegin).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 4372A 42504816 esemény azt jelzi, hogy ez egy háttérbeli szemétgyűjtés, mert az utolsó mező
GCStart_V1. Ez lesz a 102019. számú szemétgyűjtés.Az
GCStartesemény azért fordul elő, mert a háttérbeli szemétgyűjtés megkezdése előtt rövid életű szemétgyűjtésre van szükség. Ez válik a 102020. számú hulladékgyűjtéssé.A 42514170-es helyszínen a 102020-as számú szemétgyűjtés befejeződött. 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-es szálon felfüggesztés történik. Ez az egyetlen alkalom, amikor a háttérszemé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
GCEndháttérben zajló 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, bármennyi átmeneti szemétgyűjtés történhet.
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:
~*tudásbázis
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[])+0x48Ha 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 módon alacsony memóriát jelző értesítést kap, és elindítja a szemétgyűjtést.
Ha a szemétgyűjtést memóriafoglalás okozta, a verem az alábbiak szerint 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[])+0x153A 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 –statPé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 objectsIsmételje meg a parancsot a 2. generáció végén:
!dumpheap –statPé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 objectsAz
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 agcrootparancsot.
Annak megállapítása, hogy a magas processzorhasználatot a szemétgyűjtés okozza-e
Korrelálja a
% Time in GCmemóriateljesítmény-számláló értékét a folyamatidővel.Ha az érték a
% Time in GCfolyamatidő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.