Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Bu makalede çöp toplama ve bellek kullanımıyla ilgili sorunlar açıklanmaktadır. Yönetilen yığınla ilgili sorunları giderir ve atık toplamanın uygulamalarınız üzerindeki etkisini en aza indirmeyi açıklar. Her sorunun, sorunları araştırmak için kullanabileceğiniz yordamlara bağlantıları vardır.
Performans analizi araçları
Aşağıdaki bölümlerde bellek kullanımı ve çöp toplama sorunlarını araştırmak için kullanılabilecek araçlar açıklanmaktadır. Bu makalenin devamında sağlanan prosedürler bu araçlarla ilgilidir.
Bellek Performansı Sayaçları
Performans verilerini toplamak için performans sayaçlarını kullanabilirsiniz. Yönergeler için bkz . Çalışma Zamanı Profili Oluşturma. .NET'teki Performans Sayaçları'nda açıklandığı gibi performans sayaçlarının .NET CLR Bellek kategorisi, çöp toplayıcı hakkında bilgi sağlar.
SOS ile hata ayıklama
Yönetilen yığındaki nesneleri incelemek için Windows Hata Ayıklayıcısı'nı (WinDbg) kullanabilirsiniz.
WinDbg'yi yüklemek için Windows için Hata Ayıklama Araçlarını İndirme sayfasından Windows için Hata Ayıklama Araçları'nı yükleyin.
Atık Toplama ETW Olayları
Windows için olay izleme (ETW), .NET tarafından sağlanan profil oluşturma ve hata ayıklama desteğini tamamlayan bir izleme sistemidir. .NET Framework 4'ten başlayarak , atık toplama ETW olayları yönetilen yığını istatistiksel bir bakış açısından analiz etmek için yararlı bilgileri yakalar. Örneğin, GCStart_V1 bir çöp toplama işlemi gerçekleşmek üzereyken ortaya çıkan olay aşağıdaki bilgileri sağlar:
- Hangi nesil nesneler toplanıyor?
- Çöp toplamayı tetikleyen şey.
- Atık toplama türü (eşzamanlı veya eşzamanlı değil).
ETW olay günlüğü verimlidir ve çöp toplamayla ilişkili performans sorunlarını maskelemeyecektir. Bir işlem, ETW olaylarıyla birlikte kendi olaylarını sağlayabilir. Kayıt altına alındığında, yığın sorunlarının nasıl ve ne zaman oluştuğunun belirlenmesi için hem uygulamanın olayları hem de çöp toplama olayları ilişkilendirilebilir. Örneğin, bir sunucu uygulaması istemci isteğinin başında ve sonunda olaylar sağlayabilir.
Profil Oluşturma API'si
Ortak dil çalışma zamanı (CLR) profil oluşturma arabirimleri, atık toplama sırasında etkilenen nesneler hakkında ayrıntılı bilgi sağlar. Çöp toplama başladığında ve sona erdiğinde profil oluşturucuya bildirim yapılabilir. Yönetilen yığındaki nesneler hakkında raporlar sağlayabilir ve her nesildeki nesnelerin tanımlanmasını da içerebilir. Daha fazla bilgi için bkz. Profil Oluşturma'ya Genel Bakış.
Profil oluşturucular kapsamlı bilgiler sağlayabilir. Ancak, karmaşık profil oluşturucular bir uygulamanın davranışını değiştirebilir.
Uygulama Etki Alanı Kaynak İzleme
.NET Framework 4'den başlayarak, Uygulama etki alanı kaynak izleme (ARM), konakların uygulama etki alanına göre CPU ve bellek kullanımını izlemesini sağlar. Daha fazla bilgi için bkz. Uygulama Etki Alanı Kaynak İzleme.
Performans sorunlarını giderme
İlk adım, sorunun aslında çöp toplama olup olmadığını belirlemektir. Bunun olduğunu belirlerseniz, sorunu gidermek için aşağıdaki listeden öğesini seçin.
- Bellek yetersiz istisnası oluşturuldu
- İşlem çok fazla bellek kullanıyor
- Çöp toplayıcı nesneleri yeterince hızlı geri kazanmıyor
- Yönetilen yığın çok parçalanmış
- Çöp toplama kesintileri çok uzun
- 0. nesil çok büyük
- Çöp toplama sırasında CPU kullanımı çok yüksek
Sorun: Bellek Yetersizliği İstisnası Oluştu
Yönetilen bir OutOfMemoryException hatasının atılması için iki geçerli durum vardır.
Sanal bellek tükeniyor.
Atık toplayıcı, sistemdeki belleği önceden belirlenmiş boyutlarda bölümlerinde ayırır. Ayırma için ek bir kesim gerekiyorsa ancak işlemin sanal bellek alanında bitişik boş blok kalmadıysa, yönetilen yığın için ayırma başarısız olur.
Ayıracak yeterli fiziksel belleğe sahip değil.
| Performans denetimleri |
|---|
|
Bellek dışı özel durumun yönetilip yönetilmediğini belirleyin. Ne kadar sanal belleğin ayrılabileceğini belirleyin. Yeterli fiziksel bellek olup olmadığını belirleyin. |
Özel durumun geçerli olmadığını belirlerseniz, aşağıdaki bilgilerle Microsoft Müşteri Hizmetleri ve Desteği'ne başvurun:
- Yönetilen yetersiz bellek istisnasına sahip yığın.
- Tam bellek dökümü.
- Sanal veya fiziksel belleğin sorun olmadığını gösteren veriler de dahil olmak üzere, bunun meşru bir bellek dışı özel durum olmadığını kanıtlayan veriler.
Sorun: İşlem çok fazla bellek kullanıyor
Yaygın bir varsayım, Windows Görev Yöneticisi'nin Performans sekmesindeki bellek kullanımı görünümünün çok fazla bellek kullanıldığını gösterebileceğidir. Ancak, bu görüntü çalışma kümesiyle ilgili; sanal bellek kullanımı hakkında bilgi sağlamaz.
Sorunun yönetilen yığından kaynaklandığını belirlerseniz, tüm desenleri belirlemek için yönetilen yığını zaman içinde ölçmeniz gerekir.
Sorunun yönetilen yığından kaynaklanmadığını belirlerseniz yerel hata ayıklamayı kullanmanız gerekir.
Sorun: Çöp Toplayıcı nesneleri yeterince hızlı geri kazanmıyor
Nesneler çöp toplama için beklendiği gibi geri kazanılmıyor gibi göründüğünde, bu nesnelere yönelik güçlü başvurular olup olmadığını belirlemeniz gerekir.
Bu sorunla, ölü bir nesne içeren nesil için çöp toplama yapılmadıysa ve bu da ölü nesnenin sonlandırıcısının çalıştırılmadığını belirtiyorsa karşılaşabilirsiniz. Örneğin, tek iş parçacıklı bir apartman (STA) uygulaması çalıştırdığınızda ve sonlandırıcı kuyruğuna hizmet veren iş parçacığı ona çağrı yapamadığında bu mümkündür.
| Performans denetimleri |
|---|
|
Nesnelere referansları denetleyin. Sonlandırıcının çalıştırılıp çalıştırılmadığını belirleyin. Sonlandırılmayı bekleyen nesneler olup olmadığını belirleyin. |
Sorun: Yönetilen Heap çok parçalanmış
Parçalanma düzeyi, oluşturma için ayrılan toplam bellek üzerindeki boş alan oranı olarak hesaplanır. 2. nesil için kabul edilebilir bir parçalanma düzeyi en fazla 20%. 2. nesil çok büyük olabileceğinden parçalanma oranı mutlak değerden daha önemlidir.
0. nesilde çok fazla boş alan olması sorun oluşturmaz çünkü bu, yeni nesnelerin ayrıldığı nesildir.
Parçalanma her zaman büyük nesne yığınında oluşur çünkü sıkıştırılmaz. Bitişik olan boş nesneler, büyük nesne ayırma isteklerini karşılamak için doğal olarak tek bir alana daraltılır.
Parçalanma, 1. nesil ve 2. nesillerde sorun haline gelebilir. Bu nesiller bir çöp toplama işleminden sonra büyük miktarda boş alana sahipse, uygulamanın nesne kullanımının değiştirilmesi gerekebilir ve uzun süreli nesnelerin ömrünü yeniden değerlendirmeyi düşünmelisiniz.
Nesnelerin aşırı sabitlenmeleri parçalanmayı artırabilir. Parçalanma yüksekse, çok fazla nesne sabitlenmiş olabilir.
Sanal belleğin parçalanması çöp toplayıcının kesim eklemesini engelliyorsa, bunun nedenleri şunlardan biri olabilir:
Birçok küçük derlemenin sık sık yüklenmesi ve boşaltılması.
Yönetilmeyen kodla birlikte çalışırken COM nesnelerine çok fazla referans tutma.
Büyük nesne yığınının yığın kesimlerini sık sık ayırıp boşaltmasına neden olan büyük geçici nesneler oluşturulması.
Bir uygulama, CLR'yi çalıştırırken çöp toplayıcının bölümlerini tutmasını isteyebilir. Bu, segment ayırma sıklığını azaltır. Bu, STARTUP_FLAGS Numaralandırmasında STARTUP_HOARD_GC_VM bayrağı kullanılarak gerçekleştirilir.
| Performans denetimleri |
|---|
|
Yönetilen yığındaki boş alan miktarını belirleyin. Sabitlenmiş nesnelerin sayısını belirleyin. |
Parçalanmanın meşru bir nedeni olmadığını düşünüyorsanız Microsoft Müşteri Hizmetleri ve Desteği'ne başvurun.
Sorun: Çöp Toplama Duraklamaları Çok Uzun
Atık toplama yumuşak gerçek zamanlı olarak çalışır, bu nedenle bir uygulamanın bazı duraklamaları tolere edebilmesi gerekir. Yumuşak gerçek zamanlı için bir ölçüt, işlemlerin 95% zamanında bitmesi gerektiğidir.
Eşzamanlı çöp toplamada, yönetilen iş parçacıklarının bir toplama sırasında çalışmasına izin verilir, bu da duraklamaların çok az olduğu anlamına gelir.
Kısa ömürlü çöp toplama (0 ve 1 nesilleri) yalnızca birkaç milisaniye sürer, bu nedenle duraklamaların azaltılması genellikle mümkün değildir. Ancak, bir uygulamanın ayırma isteklerinin desenini değiştirerek 2. nesil koleksiyonlardaki duraklamaları azaltabilirsiniz.
Daha doğru bir diğer yöntem de atık toplama ETW olaylarını kullanmaktır. Bir olay dizisi için zaman damgası farklarını ekleyerek koleksiyonların zamanlamalarını bulabilirsiniz. Tüm koleksiyon dizisi yürütme altyapısının askıya alınmasını, çöp toplamanın kendisini ve yürütme altyapısının yeniden başlatılmasını içerir.
Bir sunucunun 2. nesil bir koleksiyona sahip olup olmadığını ve istekleri başka bir sunucuya yeniden yönlendirmenin duraklamalarla ilgili sorunları kolaylaştırıp kolaylaştırmayacağını belirlemek için Çöp Toplama Bildirimleri'ni kullanabilirsiniz.
| Performans denetimleri |
|---|
|
Bir çöp toplamadaki sürenin uzunluğunu belirleyin. Çöp toplamaya neyin neden olduğunu belirleyin. |
Sorun: 0. Nesil Çok Büyük
Özellikle iş istasyonu çöp toplama yerine sunucu çöp toplama kullandığınızda, 0. nesil büyük olasılıkla 64 bit sistem üzerinde daha fazla sayıda nesneye sahip olabilir. Bunun nedeni, 0. nesil çöp toplamayı tetikleme eşiğinin bu ortamlarda daha yüksek olması ve 0. nesil koleksiyonların çok daha büyüyebileceğidir. Bir uygulama çöp toplama tetiklenmeden önce daha fazla bellek ayırdığında performans iyileştirilir.
Sorun: Çöp Toplama Sırasında CPU Kullanımı Çok Yüksek
Atık toplama sırasında CPU kullanımı yüksek olacaktır. Bir çöp toplama işleminde önemli miktarda işlem süresi harcanırsa, koleksiyon sayısı çok sıktır veya koleksiyon çok uzun sürer. Yönetilen yığındaki nesnelerin artan ayırma oranı, atık toplama işleminin daha sık gerçekleşmesine neden olur. Ayırma oranının azaltılması, çöp toplama sıklığını azaltır.
Performans sayacını Allocated Bytes/second kullanarak ayırma oranlarını izleyebilirsiniz. Daha fazla bilgi için bkz. .NET'te Performans Sayaçları.
Bir koleksiyonun süresi birincil olarak ayırmadan sonra hayatta kalan nesne sayısının bir faktörüdür. Çok sayıda nesne toplanmaya devam ederse, atık toplayıcının büyük miktarda bellekten geçmesi gerekir. Hayatta kalanları sıkıştırmak zaman alır. Bir koleksiyon sırasında kaç nesnenin işlendiğini belirlemek için, belirtilen bir nesil için çöp toplama işleminin sonunda hata ayıklayıcıda bir kesme noktası ayarlayın.
| Performans denetimleri |
|---|
|
Atık toplamadan kaynaklanan yüksek CPU kullanımı olup olmadığını belirleyin. Çöp toplama işleminin sonunda bir kesme noktası ayarlayın. |
Sorun giderme yönergeleri
Bu bölümde, araştırmalarınıza başlarken göz önünde bulundurmanız gereken yönergeler açıklanmaktadır.
İş İstasyonu veya Sunucu Çöp Toplama
Doğru çöp toplama türünü kullanıp kullanmayabileceğinizi belirleyin. Uygulamanız birden fazla iş parçacığı ve nesne örneği kullanıyorsa, iş istasyonu çöp toplama yerine sunucu çöp toplamayı tercih edin. Sunucu çöp toplama birden çok iş parçacığında çalışırken, iş istasyonu çöp toplama işlemi bir uygulamanın birden çok örneğinin kendi çöp toplama iş parçacıklarını çalıştırmasını ve CPU süresi için birbirleriyle rekabet etmesini gerektirir.
Düşük yükte olan ve arka planda nadiren görev gerçekleştiren, örneğin bir hizmet gibi bir uygulama, eş zamanlı çöp toplama devre dışı bırakıldığında iş istasyonu çöp toplamasını kullanabilir.
Yönetilen Yığın Boyutu Ne Zaman Ölçülmeli?
Profil oluşturucu kullanmadığınız sürece performans sorunlarını etkili bir şekilde tanılamak için tutarlı bir ölçüm düzeni oluşturmanız gerekir. Bir zamanlama oluşturmak için aşağıdaki noktaları göz önünde bulundurun:
- 2. nesil çöp toplama işleminden sonra ölçüm yaparsanız, yönetilen yığının tamamı çöp (ölü nesneler) içermez.
- 0. nesil çöp toplama işleminden hemen sonra ölçüm yaparsanız, 1. ve 2. nesillerdeki nesneler henüz toplanmaz.
- Bir çöp toplamadan hemen önce ölçüm yaparsanız, çöp toplama başlamadan önce mümkün olduğunca fazla ayırmayı ölçersiniz.
- Atık toplayıcı veri yapıları geçiş için geçerli bir durumda olmadığından ve size tam sonuçları veremediğinden, atık toplama sırasında ölçüm yapmak sorunludur. Bu tasarım gereğidir.
- Eşzamanlı çöp toplama ile birlikte iş istasyonu çöp toplama kullanırken, geri kazanılan nesneler sıkıştırılmaz, bu nedenle yığın boyutu aynı kalabilir veya daha büyük olabilir (parçalanma, daha büyük görünmesine neden olabilir).
- Fiziksel bellek yükü çok yüksek olduğunda 2. nesildeki eşzamanlı çöp toplama işlemi gecikir.
Aşağıdaki yordamda, yönetilen yığını ölçebilmeniz için kesme noktasının nasıl ayarlanacağı açıklanmaktadır.
Çöp toplamanın sonunda bir kesme noktası ayarlamak için
SOS hata ayıklayıcısı uzantısının yüklü olduğu WinDbg'de aşağıdaki komutu girin:
bp mscorwks!WKS::GCHeap::RestartEE "j (dwo(mscorwks!WKS::GCHeap::GcCondemnedGeneration)==2) 'kb';'g'"İstenen nesile ayarlayın
GcCondemnedGeneration. Bu komut özel simgeler gerektirir.Bu komut, 2. nesil nesneler atık toplama için geri kazanıldıktan sonra yürütülürse
RestartEEbir kesmeye zorlar.Sunucu çöp toplama sırasında, yalnızca bir işlem birimi
RestartEEçağırır, bu nedenle kesme noktası 2. nesil çöp toplama sırasında yalnızca bir kez oluşacaktır.
Performans denetimi yordamları
Bu bölümde, performans sorununuzun nedenini yalıtmak için aşağıdaki yordamlar açıklanmaktadır:
- Sorunun çöp toplamadan kaynaklanıp kaynak olmadığını belirleyin.
- Bellek dışı özel durumun yönetilip yönetilmediğini belirleyin.
- Ne kadar sanal belleğin ayrılabileceğini belirleyin.
- Yeterli fiziksel bellek olup olmadığını belirleyin.
- Yönetilen yığının ne kadar bellek işlediğini belirleyin.
- Yönetilen yığının ne kadar bellek ayırdığını belirleyin.
- 2. nesildeki büyük nesneleri belirleme.
- Nesneler için referansları belirle.
- Sonlandırıcının çalıştırılıp çalıştırılmadığını belirleyin.
- Sonlandırılmayı bekleyen nesneler olup olmadığını belirleyin.
- Yönetilen yığındaki boş alan miktarını belirleyin.
- Sabitlenmiş nesnelerin sayısını belirleyin.
- Bir çöp toplamadaki sürenin uzunluğunu belirleyin.
- Çöp toplamayı neyin tetiklediğini belirleyin.
- Atık toplamadan kaynaklanan yüksek CPU kullanımı olup olmadığını belirleyin.
Sorunun çöp toplamadan kaynaklanıp kaynak olmadığını belirlemek için
Aşağıdaki iki bellek performansı sayacını inceleyin:
% GC'de Zaman. Son çöp toplama döngüsünden sonra bir çöp toplama işlemi gerçekleştirmek için harcanan geçen sürenin yüzdesini görüntüler. Çöp toplayıcının yönetilen yığın alanını kullanılabilir hale getirmek için çok fazla zaman harcayıp harcamadığını belirlemek için bu sayacı kullanın. Çöp toplamada harcanan süre görece düşükse, bu yönetilen yığının dışında bir kaynak sorununa işaret edebilir. Eşzamanlı veya arka plan çöp toplama söz konusu olduğunda bu sayaç doğru olmayabilir.
# Toplam işlenen Bayt sayısı. Çöp toplayıcı tarafından şu anda ayrılan sanal bellek miktarını görüntüler. Çöp toplayıcı tarafından tüketilen belleğin uygulamanızın kullandığı belleğin aşırı bir bölümü olup olmadığını belirlemek için bu sayacı kullanın.
Bellek performans sayaçlarının çoğu her çöp toplama işleminin sonunda güncelleştirilir. Bu nedenle, bunlar hakkında bilgi almak istediğiniz geçerli koşulları yansıtmayabilir.
Bellek dışı özel durumun yönetilip yönetilmediğini belirlemek için
SOS hata ayıklayıcısı uzantısının yüklü olduğu WinDbg veya Visual Studio hata ayıklayıcısına yazdırma özel durumu (
pe) komutunu girin:!peÖzel durum yönetiliyorsa, OutOfMemoryException aşağıdaki örnekte gösterildiği gibi özel durum türü olarak görüntülenir.
Exception object: 39594518 Exception type: System.OutOfMemoryException Message: <none> InnerException: <none> StackTrace (generated):Çıkış bir özel durum belirtmezse, bellek dışı özel durumun hangi iş parçacığından olduğunu belirlemeniz gerekir. Tüm iş parçacıklarını çağrı yığınlarıyla göstermek için hata ayıklayıcıya aşağıdaki komutu girin:
~\*kbİstisna çağrılarına sahip olan yığını içeren iş parçacığı
RaiseTheExceptionargümanıyla belirtilir. Bu yönetilen özel durum nesnesidir.28adfb44 7923918f 5b61f2b4 00000000 5b61f2b4 mscorwks!RaiseTheException+0xa0İç içe özel durumların dökümünü almak için aşağıdaki komutu kullanabilirsiniz.
!pe -nestedÖzel durum bulamazsanız, bellek dışı özel durum yönetilmeyen koddan kaynaklanır.
Ne kadar sanal belleğin ayrılabileceğini belirlemek için
SOS hata ayıklayıcısı uzantısının yüklü olduğu WinDbg'de, en büyük boş bölgeyi almak için aşağıdaki komutu girin:
!address -summaryEn büyük ücretsiz bölge aşağıdaki çıkışta gösterildiği gibi görüntülenir.
Largest free region: Base 54000000 - Size 0003A980Bu örnekte, en büyük boş bölgenin boyutu yaklaşık 24000 KB'dir (onaltılık olarak 3A980). Bu bölge, çöp toplayıcının bir segment için ihtiyaç duyduğundan çok daha küçüktür.
-veya-
vmstatkomutunu kullanın:!vmstatEn büyük boş bölge, aşağıdaki çıkışta gösterildiği gibi MAXIMUM sütunundaki en büyük değerdir.
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
Yeterli fiziksel bellek olup olmadığını belirlemek için
Windows Görev Yöneticisi'ni başlatın.
Performancesekmesinde, taahhüt edilen değere bakın. (Windows 7'deCommit (KB)öğesineSystem groupiçinde bakın.)Totaldeğerine yakınsaLimit, fiziksel belleğiniz azalıyordur.
Yönetilen yığının ne kadar bellek taahhüt ettiğini belirlemek için
Yönetilen yığının
# Total committed bytesişlediği bayt sayısını almak için bellek performans sayacını kullanın. Çöp toplayıcı, bir segmentteki parçaları gerektiği gibi tahsis eder, hepsini aynı anda yapmaz.Uyarı
Yönetilen yığın tarafından gerçek bellek kullanımını temsil etmediğinden performans sayacını kullanmayın
# Bytes in all Heaps. Bir neslin boyutu bu değere dahil edilir ve aslında eşik boyutudur, yani nesil nesnelerle doluysa çöp toplamaya neden olan boyuttur. Bu nedenle, bu değer genellikle sıfırdır.
Yönetilen yığının ne kadar bellek ayırdığını belirlemek için
Bellek performans sayacını
# Total reserved byteskullanın.Çöp toplayıcı bellek segmentlerini ayırır ve bir segmentin nereden başlayacağını
eeheapkomutunu kullanarak belirleyebilirsiniz.Önemli
Çöp toplayıcının her segment için ayırabileceği bellek miktarını belirleyebilirsiniz ancak kesim boyutu uygulamaya özgüdür ve düzenli güncelleştirmeler de dahil olmak üzere herhangi bir zamanda değiştirilebilir. Uygulamanız hiçbir zaman belirli bir segment boyutuyla ilgili varsayımlarda bulunmamalı veya segment ayırmaları için kullanılabilir bellek miktarını yapılandırmaya çalışmamalıdır.
SOS hata ayıklayıcısı uzantısının yüklü olduğu WinDbg veya Visual Studio hata ayıklayıcısına aşağıdaki komutu girin:
!eeheap -gcSonuç aşağıdaki gibidir.
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)"segment" tarafından belirtilen adresler, segmentlerin başlangıç adresleridir.
2. nesildeki büyük nesneleri belirlemek için
SOS hata ayıklayıcısı uzantısının yüklü olduğu WinDbg veya Visual Studio hata ayıklayıcısına aşağıdaki komutu girin:
!dumpheap –statYönetilen yığın büyükse,
dumpheap'ün tamamlanması biraz zaman alabilir.En çok alan kullanan nesneleri listelediklerinden, çıkışın son birkaç satırıyla çözümlemeye başlayabilirsiniz. Örneğin:
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 objectsListelenen son nesne bir dizedir ve en fazla alanı kaplar. Dize nesnelerinizin nasıl iyileştirilebileceğini görmek için uygulamanızı inceleyebilirsiniz. 150 ile 200 bayt arasındaki dizeleri görmek için aşağıdakileri girin:
!dumpheap -type System.String -min 150 -max 200Sonuçların bir örneği aşağıda verilmiştir.
Address MT Size Gen 1875d2c0 790fa3e0 152 2 System.String HighlightNullStyle_Blotter_PendingOrder-11_Blotter_PendingOrder-11 …Kimlik için dize yerine tamsayı kullanmak daha verimli olabilir. Aynı dize binlerce kez yineleniyorsa, dize havuzlama kullanmayı göz önünde bulundurun. Dize havuzu hakkında daha fazla bilgi almak için String.Intern yönteminin referans konusuna bakın.
Nesnelere yapılan atıfları belirlemek için
SOS hata ayıklayıcısı uzantısının yüklü olduğu WinDbg'de, nesnelere yapılan başvuruları listelemek için aşağıdaki komutu girin:
!gcroot-veya-
Belirli bir nesneye ait referansları belirlemek için adresi ekleyin:
!gcroot 1c37b2acYığınlarda bulunan kökler yanlış pozitifler olabilir. Daha fazla bilgi edinmek için
!help gcrootkomutunu kullanın.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 484Komutun
gcroottamamlanması uzun sürebilir. Çöp toplama tarafından geri kazanılmayan tüm nesneler canlı bir nesnedir. Başka bir deyişle, bir kök doğrudan veya dolaylı olarak nesneyi tutuyor, bu nedenlegcrootnesneye yol bilgisi döndürmelidir. Döndürülen grafikleri incelemeniz ve bu nesnelere neden hala başvurıldığını görmeniz gerekir.
Sonlandırıcının çalıştırılıp çalıştırılmadığını belirlemek için
Aşağıdaki kodu içeren bir test programı çalıştırın:
GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect();Test sorunu çözerse, bu, bu nesnelerin finalizörleri askıya alındığı için çöp toplayıcının nesneleri geri kazanamadığı anlamına gelir. GC.WaitForPendingFinalizers yöntemi, sonlandırıcıların görevlerini tamamlamasına olanak tanır ve sorunu çözer.
Sonlandırılmayı bekleyen nesneler olup olmadığını belirlemek için
SOS hata ayıklayıcısı uzantısının yüklü olduğu WinDbg veya Visual Studio hata ayıklayıcısına aşağıdaki komutu girin:
!finalizequeueSonlandırma için hazır olan nesne sayısına bakın. Sayı yüksekse, bu sonlandırıcıların neden hiç ilerleme göstermediğini veya yeterince hızlı ilerleyemediğini incelemeniz gerekir.
İş parçacıklarının çıktısını almak için aşağıdaki komutu girin:
!threads -specialBu komut aşağıdaki gibi bir çıkış sağlar.
OSID Special thread type 2 cd0 DbgHelper 3 c18 Finalizer 4 df0 GC SuspendEESonlandırıcı iş parçacığı, varsa şu anda hangi sonlandırıcının çalıştırıldığını gösterir. Sonlandırıcı iş parçacığı herhangi bir sonlandırıcı çalıştırmadığında, görevini yapması için bir olayın ona sinyal vermesini bekler. Çoğu zaman sonlandırıcı iş parçacığını bu durumda görürsünüz çünkü THREAD_HIGHEST_PRIORITY ile çalışır ve varsa sonlandırıcıları çok hızlı bir şekilde çalıştırmayı tamamlaması gerekir.
Yönetilen yığındaki boş alan miktarını belirlemek için
SOS hata ayıklayıcısı uzantısının yüklü olduğu WinDbg veya Visual Studio hata ayıklayıcısına aşağıdaki komutu girin:
!dumpheap -type Free -statBu komut, aşağıdaki örnekte gösterildiği gibi yönetilen yığındaki tüm boş nesnelerin toplam boyutunu görüntüler.
total 230 objects Statistics: MT Count TotalSize Class Name 00152b18 230 40958584 Free Total 230 objects0. nesildeki boş alanı belirlemek için, nesillere göre bellek tüketimi bilgileri için aşağıdaki komutu girin:
!eeheap -gcBu komut çıktıyı aşağıdakine benzer şekilde görüntüler. Son satır geçici segmenti gösterir.
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)0. nesil tarafından kullanılan alanı hesaplayın:
? 49e05d04-0x49521f8cSonuç aşağıdaki gibidir. 0. nesil yaklaşık 9 MB'tır.
Evaluate expression: 9321848 = 008e3d78Aşağıdaki komut, nesil 0 aralığındaki boş alanı döküm eder:
!dumpheap -type Free -stat 0x49521f8c 49e05d04Sonuç aşağıdaki gibidir.
------------------------------ 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 objectsBu çıkış, yığının 0. nesil bölümünün nesneler için 9 MB alan kullandığını ve 7 MB boşluğa sahip olduğunu gösterir. Bu analiz, 0. neslin parçalanmayla ne ölçüde katkıda bulunduğu gösterir. Bu yığın kullanım miktarı, uzun vadeli nesnelerin parçalanmaya neden olması nedeniyle toplam miktardan düşülmelidir.
Sabitlenmiş öğe sayısını belirlemek için
SOS hata ayıklayıcısı uzantısının yüklü olduğu WinDbg veya Visual Studio hata ayıklayıcısına aşağıdaki komutu girin:
!gchandlesGörüntülenen istatistikler, sabitlenmiş tanıtıcıların sayısını içerir, aşağıdaki örnekte gösterildiği gibi.
GC Handle Statistics: Strong Handles: 29 Pinned Handles: 10
Çöp toplamadaki süreyi belirlemek için
Bellek performans sayacını
% Time in GCinceleyin.Değer, örnek bir aralık süresi kullanılarak hesaplanır. Sayaçlar her çöp toplama işleminin sonunda güncelleştirildiğinden, aralık boyunca hiçbir koleksiyon gerçekleşmediyse geçerli örnek önceki örnekle aynı değere sahip olur.
Toplama süresi, örnek aralık süresi ile yüzde değeri çarpılarak elde edilir.
Aşağıdaki veriler, 8 saniyelik bir çalışma için iki saniyelik dört örnekleme aralığını göstermektedir.
Gen0,Gen1veGen2sütunları, bu nesil için aralığın sonuna kadar tamamlanan toplam çöp toplama sayısını gösterir.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 3Bu bilgiler çöp toplama işleminin ne zaman gerçekleştiğini göstermez, ancak belirli bir zaman aralığında oluşan çöp toplamalarının sayısını belirleyebilirsiniz. En kötü durum varsayarsak, onuncu nesil 0 çöp toplama işlemi ikinci aralığın başında, on birinci nesil 0 çöp toplama işlemi ise üçüncü aralığın sonunda tamamlanmıştır. Onuncu ve on birinci çöp toplamanın sonu arasındaki süre yaklaşık 2 saniyedir ve performans sayacı 3%gösterir, bu nedenle on birinci nesil 0 çöp toplama süresi (2 saniye * 3% = 60ms) olur.
Sonraki örnekte beş aralık vardır.
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İkinci nesil 2 çöp toplama işlemi dördüncü aralıkta başladı ve beşinci aralıkta tamamlandı. En kötü durum varsayarsak, son çöp toplama üçüncü aralığın başında tamamlanan bir 0. nesil toplama içindi ve 2. nesil çöp toplama beşinci aralığın sonunda tamamlandı. Bu nedenle, nesil 0 çöp toplama ile 2. nesil çöp toplamanın sonu arasındaki süre 4 saniyedir.
% Time in GCSayaç 20%olduğundan, 2. nesil çöp toplama işleminin süresi üst sınırıdır (4 saniye * 20% = 800ms).Alternatif olarak, atık toplama ETW olaylarını kullanarak bir çöp toplamanın uzunluğunu belirleyebilir ve atık toplama süresini belirlemek için bilgileri analiz edebilirsiniz.
Örneğin, aşağıdaki veriler eşzamanlı olmayan çöp toplama sırasında oluşan bir olay dizisini gösterir.
Timestamp Event name 513052 GCSuspendEEBegin_V1 513078 GCSuspendEEEnd 513090 GCStart_V1 517890 GCEnd_V1 517894 GCHeapStats 517897 GCRestartEEBegin 517918 GCRestartEEEndYönetilen iş parçacığının askıya alınması 26 mikrosaniye (
GCSuspendEEEnd–GCSuspendEEBegin_V1) sürdü.Gerçek çöp toplama 4,8ms (
GCEnd_V1–GCStart_V1) sürdü.Yönetilen iş parçacıklarının devam ettirilmesi 21 us (
GCRestartEEEnd–GCRestartEEBegin) sürdü.Aşağıdaki çıkış arka plan çöp toplama için bir örnek sağlar ve işlem, iş parçacığı ve olay alanlarını içerir. (Tüm veriler gösterilmez.)
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 4372GCStart_V142504816'daki olay, bunun bir arka plan çöp toplaması olduğunu gösterir çünkü son alan şeklindedir1. Bu işlem, 102019 numaralı çöp toplama olur.Olay
GCStart, arka plan çöp toplama işlemine başlamadan önce kısa süreli çöp toplamaya ihtiyaç duymanız nedeniyle oluşur. Bu, 102020 no'lu çöp toplama haline gelir.42514170 102020 no'lu çöp toplama işlemi tamamlanmaktadır. Yönetilen iş parçacıkları bu noktada yeniden başlatılır. Bu işlem, bu arka plan çöp toplama işlemini tetikleyen 4372 iş parçacığında tamamlandı.
4744 düğümünde bir askıya alma gerçekleşiyor. Bu, arka plan çöp toplama işleminin yönetilen iş parçacıklarını askıya almak zorunda kaldığı tek zamandır. Bu süre yaklaşık 99ms 'dir ((63784407-63685394)/1000).
GCEndarka plan çöp toplama olayı 89931423'te. Bu, arka plan çöp toplama işleminin yaklaşık 47 saniye sürdüğü anlamına gelir ((89931423-42504816)/1000).Yönetilen iş parçacıkları çalışırken, herhangi bir sayıda geçici çöp toplama işleminin gerçekleştiğini görebilirsiniz.
Çöp toplamayı neyin tetiklediğini belirlemek için
SOS hata ayıklayıcısı uzantısı yüklü WinDbg veya Visual Studio hata ayıklayıcısında, çağrı yığınlarıyla tüm iş parçacıklarını göstermek için aşağıdaki komutu girin:
~*KB
Bu komut çıktıyı aşağıdakine benzer şekilde görüntüler.
0012f3b0 79ff0bf8 mscorwks!WKS::GCHeap::GarbageCollect 0012f454 30002894 mscorwks!GCInterface::CollectGeneration+0xa4 0012f490 79fa22bd fragment_ni!request.Main(System.String[])+0x48Atık toplama işlemi işletim sisteminden gelen düşük bellek bildiriminden kaynaklanıyorsa, iş parçacığının sonlandırıcı iş parçacığı olması dışında çağrı yığını benzerdir. Sonlandırıcı iş parçacığı zaman uyumsuz bir düşük bellek bildirimi alır ve çöp toplayıcıyı tetikler.
Atık toplama işlemi bellek ayırmadan kaynaklanıyorsa yığın aşağıdaki gibi görünür:
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[])+0x153Tam zamanında yardımcı (
JIT_New*) sonundaGCHeap::GarbageCollectGeneration'yi çağırır. 2. nesil çöp toplamaların ayırmalardan kaynaklandığını belirlerseniz, hangi nesnelerin 2. nesil çöp toplama tarafından toplandığını ve bunların nasıl önleneceğini belirlemeniz gerekir. Başka bir ifadeyle, 2. nesil çöp toplamanın başlangıcı ve sonu ile 2. nesil koleksiyonuna neden olan nesneler arasındaki farkı belirlemek istiyorsunuz.Örneğin, 2. nesil koleksiyonun başlangıcını göstermek için hata ayıklayıcıya aşağıdaki komutu girin:
!dumpheap –statÖrnek çıkış (en çok alan kullanan nesneleri göstermek için kısaltılmış):
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 objects2. neslin sonundaki komutu yineleyin:
!dumpheap –statÖrnek çıkış (en çok alan kullanan nesneleri göstermek için kısaltılmış):
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 objectsNesneler
double[]çıktının sonundan kayboldu, yani toplandılar. Bu nesneler yaklaşık 70 MB'tır. Kalan nesneler çok fazla değişmedi. Bu nedenle, bu 2. nesil çöp toplamanın nedeni budouble[]nesnelerdi. Sonraki adımınız nesnelerin neden orada olduğunu ve nedendouble[]öldüklerini belirlemektir. Kod geliştiricisine bu nesnelerin nereden geldiğini sorabilir veya komutunu kullanabilirsinizgcroot.
Yüksek CPU kullanımının çöp toplamadan kaynaklanıp kaynaklanıp kaynak edilmediğini belirlemek için
Bellek performansı sayacı değerini işlem süresiyle ilişkilendirin
% Time in GC.% Time in GCDeğer işlem süresiyle aynı anda ani bir artış gösterirse, atık toplama işlemi yüksek CPU kullanımına neden olur. Aksi takdirde, yüksek kullanımın nerede oluştuğunu bulmak için uygulamanın profilini oluşturun.