Memóriaszivárgás hibakeresése a .NET-ben
Ez a cikk a következőre vonatkozik: ✔️ .NET Core 3.1 SDK és újabb verziók
A memória kiszivároghat, ha az alkalmazás olyan objektumokra hivatkozik, amelyekre már nincs szüksége a kívánt feladat végrehajtásához. Az objektumokra való hivatkozás megakadályozza, hogy a szemétgyűjtő visszanyerje a felhasznált memóriát. Ez teljesítménycsökkenést és kivételt OutOfMemoryException eredményezhet.
Ez az oktatóanyag bemutatja azokat az eszközöket, amelyek segítségével elemezheti a memóriaszivárgást egy .NET-alkalmazásban a .NET diagnosztikai parancssori eszközeivel. Ha Windows rendszeren dolgozik, előfordulhat, hogy a Visual Studio memóriadiagnosztikai eszközeit használhatja a memóriaszivárgás hibakereséséhez.
Ez az oktatóanyag egy mintaalkalmazást használ, amely szándékosan kiszivárogtatja a memóriát gyakorlatként. Elemezheti azokat az alkalmazásokat is, amelyek véletlenül kiszivárogtatják a memóriát.
Az oktatóanyag során az alábbi lépéseket fogja végrehajtani:
- A felügyelt memóriahasználat vizsgálata dotnet-counters használatával.
- Memóriaképfájl létrehozása.
- Elemezze a memóriahasználatot a memóriaképfájl használatával.
Előfeltételek
Az oktatóanyag a következőket használja:
- .NET Core 3.1 SDK vagy újabb verzió.
- dotnet-counters a felügyelt memóriahasználat ellenőrzéséhez.
- dotnet-dump egy memóriaképfájl gyűjtéséhez és elemzéséhez (beleértve az SOS hibakeresési bővítményt).
- Minta hibakeresési célalkalmazás diagnosztizálásához.
Az oktatóanyag feltételezi, hogy a mintaalkalmazások és -eszközök telepítve vannak, és használatra készek.
Felügyelt memóriahasználat vizsgálata
Mielőtt elkezdené összegyűjteni a diagnosztikai adatokat, hogy segítsen a forgatókönyv kiváltó okának elhárításában, győződjön meg arról, hogy valóban memóriaszivárgást tapasztal (a memóriahasználat növekedése). Ezt a dotnet-counters eszközzel ellenőrizheti.
Nyisson meg egy konzolablakot, és keresse meg azt a könyvtárat, ahol letöltötte és kibontotta a hibakeresési célpéldányt. Futtassa a célt:
dotnet run
Egy külön konzolon keresse meg a folyamatazonosítót:
dotnet-counters ps
A kimenetnek a következőhöz hasonlónak kell lennie:
4807 DiagnosticScena /home/user/git/samples/core/diagnostics/DiagnosticScenarios/bin/Debug/netcoreapp3.0/DiagnosticScenarios
Most ellenőrizze a felügyelt memóriahasználatot a dotnet-counters eszközzel. A --refresh-interval
frissítés közötti másodpercek számát adja meg:
dotnet-counters monitor --refresh-interval 1 -p 4807
Az élő kimenetnek a következőhöz hasonlónak kell lennie:
Press p to pause, r to resume, q to quit.
Status: Running
[System.Runtime]
# of Assemblies Loaded 118
% Time in GC (since last GC) 0
Allocation Rate (Bytes / sec) 37,896
CPU Usage (%) 0
Exceptions / sec 0
GC Heap Size (MB) 4
Gen 0 GC / sec 0
Gen 0 Size (B) 0
Gen 1 GC / sec 0
Gen 1 Size (B) 0
Gen 2 GC / sec 0
Gen 2 Size (B) 0
LOH Size (B) 0
Monitor Lock Contention Count / sec 0
Number of Active Timers 1
ThreadPool Completed Work Items / sec 10
ThreadPool Queue Length 0
ThreadPool Threads Count 1
Working Set (MB) 83
Az alábbi sorra összpontosítva:
GC Heap Size (MB) 4
Láthatja, hogy a felügyelt halommemória közvetlenül az indítás után 4 MB.
Most nyissa meg az URL-címet https://localhost:5001/api/diagscenario/memleak/20000
.
Figyelje meg, hogy a memóriahasználat 30 MB-ra nőtt.
GC Heap Size (MB) 30
A memóriahasználat figyelésével nyugodtan kijelentheti, hogy a memória növekszik vagy kiszivárog. A következő lépés a megfelelő adatok összegyűjtése a memóriaelemzéshez.
Memóriakép létrehozása
A lehetséges memóriavesztések elemzésekor hozzá kell férnie az alkalmazás memóriakészletéhez a memória tartalmának elemzéséhez. Az objektumok közötti kapcsolatokat vizsgálva elméleteket hozhat létre arról, hogy miért nem szabadít fel memóriát. Gyakori diagnosztikai adatforrás a Windows memóriaképe, vagy a Linuxon ezzel egyenértékű mag memóriaképe. A .NET-alkalmazások memóriaképének létrehozásához használhatja a dotnet-dump eszközt.
A korábban elindított hibakeresési mintacél használatával futtassa a következő parancsot egy Linux-mag memóriakép létrehozásához:
dotnet-dump collect -p 4807
Az eredmény egy központi memóriakép, amely ugyanabban a mappában található.
Writing minidump with heap to ./core_20190430_185145
Complete
Megjegyzés:
Az idő múlásával történő összehasonlításhoz hagyja, hogy az eredeti folyamat az első memóriakép összegyűjtése után is futjon, és gyűjtsön egy második memóriaképet ugyanúgy. Ezután két memóriaképet fog létrehozni egy adott időszak alatt, amelyeket összehasonlítva láthatja, hogy hol növekszik a memóriahasználat.
A sikertelen folyamat újraindítása
A memóriakép összegyűjtése után elegendő információval kell rendelkeznie a sikertelen folyamat diagnosztizálásához. Ha a sikertelen folyamat egy éles kiszolgálón fut, a folyamat újraindításával ideális idő a rövid távú szervizelésre.
Ebben az oktatóanyagban végzett a minta hibakeresési céllal , és bezárhatja azt. Lépjen a kiszolgálót indító terminálra, és nyomja le a Ctrl+C billentyűkombinációt.
Az alapvető memóriakép elemzése
Most, hogy létrehozott egy alapvető memóriaképet, használja a dotnet-dump eszközt a memóriakép elemzéséhez:
dotnet-dump analyze core_20190430_185145
Hol core_20190430_185145
található az elemezni kívánt alapvető memóriakép neve.
Megjegyzés:
Ha hibaüzenet jelenik meg, amely arra panaszkodik, hogy libdl.so nem található, előfordulhat, hogy telepítenie kell a libc6-dev csomagot. További információ: A .NET előfeltételei Linuxon.
Ekkor megjelenik egy üzenet, amelyben SOS-parancsokat adhat meg. Általában az első dolog, amit meg szeretne nézni, a felügyelt halom teljes állapota:
> dumpheap -stat
Statistics:
MT Count TotalSize Class Name
...
00007f6c1eeefba8 576 59904 System.Reflection.RuntimeMethodInfo
00007f6c1dc021c8 1749 95696 System.SByte[]
00000000008c9db0 3847 116080 Free
00007f6c1e784a18 175 128640 System.Char[]
00007f6c1dbf5510 217 133504 System.Object[]
00007f6c1dc014c0 467 416464 System.Byte[]
00007f6c21625038 6 4063376 testwebapi.Controllers.Customer[]
00007f6c20a67498 200000 4800000 testwebapi.Controllers.Customer
00007f6c1dc00f90 206770 19494060 System.String
Total 428516 objects
Itt láthatja, hogy a legtöbb objektum vagy String
Customer
objektum.
A metódustáblával (MT) ismét használhatja a dumpheap
parancsot az összes példány listájának String
lekéréséhez:
> dumpheap -mt 00007f6c1dc00f90
Address MT Size
...
00007f6ad09421f8 00007faddaa50f90 94
...
00007f6ad0965b20 00007f6c1dc00f90 80
00007f6ad0965c10 00007f6c1dc00f90 80
00007f6ad0965d00 00007f6c1dc00f90 80
00007f6ad0965df0 00007f6c1dc00f90 80
00007f6ad0965ee0 00007f6c1dc00f90 80
Statistics:
MT Count TotalSize Class Name
00007f6c1dc00f90 206770 19494060 System.String
Total 206770 objects
Mostantól a gcroot
példányon lévő System.String
paranccsal megtekintheti, hogyan és miért gyökerezik az objektum:
> gcroot 00007f6ad09421f8
Thread 3f68:
00007F6795BB58A0 00007F6C1D7D0745 System.Diagnostics.Tracing.CounterGroup.PollForValues() [/_/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/CounterGroup.cs @ 260]
rbx: (interior)
-> 00007F6BDFFFF038 System.Object[]
-> 00007F69D0033570 testwebapi.Controllers.Processor
-> 00007F69D0033588 testwebapi.Controllers.CustomerCache
-> 00007F69D00335A0 System.Collections.Generic.List`1[[testwebapi.Controllers.Customer, DiagnosticScenarios]]
-> 00007F6C000148A0 testwebapi.Controllers.Customer[]
-> 00007F6AD0942258 testwebapi.Controllers.Customer
-> 00007F6AD09421F8 System.String
HandleTable:
00007F6C98BB15F8 (pinned handle)
-> 00007F6BDFFFF038 System.Object[]
-> 00007F69D0033570 testwebapi.Controllers.Processor
-> 00007F69D0033588 testwebapi.Controllers.CustomerCache
-> 00007F69D00335A0 System.Collections.Generic.List`1[[testwebapi.Controllers.Customer, DiagnosticScenarios]]
-> 00007F6C000148A0 testwebapi.Controllers.Customer[]
-> 00007F6AD0942258 testwebapi.Controllers.Customer
-> 00007F6AD09421F8 System.String
Found 2 roots.
Láthatja, hogy az String
objektum közvetlenül az Customer
objektum tulajdonában van, és közvetetten egy CustomerCache
objektum tartja.
Folytathatja az objektumok memóriaképének kiírását, így láthatja, hogy a legtöbb String
objektum hasonló mintát követ. Ezen a ponton a vizsgálat elegendő információt szolgáltatott a kód alapvető okának azonosításához.
Ez az általános eljárás lehetővé teszi a főbb memóriaszivárgások forrásának azonosítását.
Clean up resources
Ebben az oktatóanyagban elindított egy minta webkiszolgálót. Ezt a kiszolgálót le kellett volna állítani a sikertelen folyamat újraindítása szakaszban leírtak szerint.
A létrehozott memóriaképfájlt is törölheti.
Kapcsolódó információk
- dotnet-trace to list processes
- dotnet-counters a felügyelt memóriahasználat ellenőrzéséhez
- dotnet-dump a memóriaképfájl gyűjtéséhez és elemzéséhez
- dotnet/diagnostics
- Memóriaszivárgások hibakeresése a Visual Studióval