SORU
26 Mart 2009, PERŞEMBE


Büyük Nesne Yığın Parçalamayı

C#/.Üzerinde çalışıyorum NET uygulama yavaş bir bellek sızıntısı muzdarip. SOS ile KT neler olduğunu belirlemek için denemek için kullandım ama veri biriniz bunu daha önce karşılaşmış olabilir umuyordum çok mantıklı görünmüyor.

Uygulama 64 bit çerçevesi üzerinde çalışıyor. Sürekli olarak bir uzak ana bilgisayara veri hesaplama serialising ve Büyük Nesne Yığın (LOH) epey vuruyor. Hesaplama tamamlandı ve uzak ana bilgisayara gönderilen sonra bellek serbest olmalıdır. ancak, geçici olmasını umuyorum LOH nesnelerin çoğu: Benim gördüğüm şey, ancak, nesne dizileri bellek boş bloklar ile, örneğin, LOH, rasgele bir kesimi alarak aralanmış (canlı) çok sayıda

0:000> !DumpHeap 000000005b5b1000  000000006351da10
         Address               MT     Size
...
000000005d4f92e0 0000064280c7c970 16147872
000000005e45f880 00000000001661d0  1901752 Free
000000005e62fd38 00000642788d8ba8     1056       <--
000000005e630158 00000000001661d0  5988848 Free
000000005ebe6348 00000642788d8ba8     1056
000000005ebe6768 00000000001661d0  6481336 Free
000000005f214d20 00000642788d8ba8     1056
000000005f215140 00000000001661d0  7346016 Free
000000005f9168a0 00000642788d8ba8     1056
000000005f916cc0 00000000001661d0  7611648 Free
00000000600591c0 00000642788d8ba8     1056
00000000600595e0 00000000001661d0   264808 Free
...

Açıkçası bu benim uygulama her hesaplanırken ömürlü uzun, büyük nesneler oluşturmak olsaydı durumda olması beklenir. (Bunu yapar ve LOH parçalanma derecesi olacak kabul ediyorum ama sorun burada değil.) Sorun kodda oluşturulan göremiyorum hangi bir şekilde kök salmış kalan hangi çöplükte yukarıda gördüğünüz çok küçük (1056 bayt) nesne dizileri.

Ayrıca unutmayın KT yığın kesimi dökülür türü bildiriyor: eğer bu ilgili olup olmadığına emin değilim. Eğer (<--) işaretli nesne ben terk edersem, KT/SOS ince bildiriyor:

0:015> !DumpObj 000000005e62fd38
Name: System.Object[]
MethodTable: 00000642788d8ba8
EEClass: 00000642789d7660
Size: 1056(0x420) bytes
Array: Rank 1, Number of elements 128, Type CLASS
Element Type: System.Object
Fields:
None

Nesne dizinin tüm dizeleri ve dizeleri başvuru kodu olarak tanınır.

Ayrıca, GC gibi köklerini bulmak kuramıyorum !GCRoot komut kilitleniyor ve bir daha geri (hatta bir gecede ayrılmayı denedim) geliyor.

Yani, eğer biri çok küçük (<85k) bu nesne dizileri LOH düşmek olarak neden herhangi bir ışık tutabilir eğer çok sevinirim: durumlar ne olacak .NET orada küçük bir nesne bir dizi koymak? Ayrıca, kimse bu nesneleri köklerini tespit etmek için alternatif bir yol biliyor mu?


Güncelleme 1

Geç saatlere kadar dün geldim başka bir teori bu nesne dizileri büyük başladı ama hafıza döker belli boş bellek blokları bırakarak daralmış olması. Bana şüpheli kılan nesne dizileri hep 1056 bayt (128 elemanları), 128 * 8 kaynaklar ve havai 32 bayt olarak görünür.

Fikir belki CLR içinde bir kütüphane veya bazı güvenli olmayan kod elemanları dizi başlığında alan sayısı bozmaya başladı. Biraz uzak bir ihtimal biliyorum


Güncelleme 2

Brian Rasmussen sayesinde (kabul cevap) sorun LOH dize stajyer tablo kaynaklanan parçalanma olarak belirlenmiştir! Bunu doğrulamak için hızlı bir test uygulaması yazdım:

static void Main()
{
    const int ITERATIONS = 100000;

    for (int index = 0; index < ITERATIONS;   index)
    {
        string str = "NonInterned"   index;
        Console.Out.WriteLine(str);
    }

    Console.Out.WriteLine("Continue.");
    Console.In.ReadLine();

    for (int index = 0; index < ITERATIONS;   index)
    {
        string str = string.Intern("Interned"   index);
        Console.Out.WriteLine(str);
    }

    Console.Out.WriteLine("Continue?");
    Console.In.ReadLine();
}

Uygulama ilk ve bir döngü içinde eşsiz dizeleri oluşturur çözümlemesi. Bu sadece bellek bu senaryoda sızıntı olmadığını ispatlamak için. Açıkçası olmamalıdır ve değildir.

İkinci döngü içinde, eşsiz dizeleri oluşturulur ve staj yaptım. Bu eylem stajyer tabloda onları kökleri. Ne fark stajyer tablo temsil edilmektedir. LOH oluşturulan 128 dize öğeleri -- sayfa -- nesne dizileri bir dizi oluşur gibi görünüyor. Bu KT/SOS: daha belirgindir

0:000> .loadby sos mscorwks
0:000> !EEHeap -gc
Number of GC Heaps: 1
generation 0 starts at 0x00f7a9b0
generation 1 starts at 0x00e79c3c
generation 2 starts at 0x00b21000
ephemeral segment allocation context: none
 segment    begin allocated     size
00b20000 00b21000  010029bc 0x004e19bc(5118396)
Large object heap starts at 0x01b21000
 segment    begin allocated     size
01b20000 01b21000  01b8ade0 0x00069de0(433632)
Total Size  0x54b79c(5552028)
------------------------------
GC Heap Size  0x54b79c(5552028)

LOH kesimi dökümü alarak ortaya koymaktadır sızıntı uygulama gördüm desen:

0:000> !DumpHeap 01b21000 01b8ade0
...
01b8a120 793040bc      528
01b8a330 00175e88       16 Free
01b8a340 793040bc      528
01b8a550 00175e88       16 Free
01b8a560 793040bc      528
01b8a770 00175e88       16 Free
01b8a780 793040bc      528
01b8a990 00175e88       16 Free
01b8a9a0 793040bc      528
01b8abb0 00175e88       16 Free
01b8abc0 793040bc      528
01b8add0 00175e88       16 Free    total 1568 objects
Statistics:
      MT    Count    TotalSize Class Name
00175e88      784        12544      Free
793040bc      784       421088 System.Object[]
Total 1568 objects

Nesne dizi boyutu benim iş istasyonu 32 bit olduğu için 528 (1056 yerine) ve uygulama sunucusu 64 bit olduğunu unutmayın. Nesne dizileri hala 128 elemanları uzun.

Bu hikayenin ahlaki çok dikkatli staj olmaktır. Eğer staj dize sonlu kümesinin bir üyesi olarak değil, daha sonra uygulama LOH parçalanma nedeniyle, en azından CLR sürüm 2 sızdırıyor.

Bizim uygulama bu durumda, unmarshalling sırasında varlık tanımlayıcı stajyerler bu deserialisation kod yolunda genel bir kod var: ben artık kesinlikle bu suçlu olduğundan şüpheleniyor. Ancak, geliştirici niyetleri varsa aynı varlık birden çok kez deserialised ise tanımlayıcı dize yalnızca bir örneği korunur emin olmak istiyorlar belli ki iyi bir hafızası vardı.

CEVAP
21 EKİM 2009, ÇARŞAMBA


Neden Microsoft basit bir API ile bize sağlayabilir .NET adlı:

GC.CompactLargeObjectHeap()

eğer bu yöntemi uygulama 10 saniye veya daha fazla ... bekle neden oluyorsa bile çökmesini ve Uygulama belleği temizlemek için yeniden başlatma gerektiren heck atıyor!

LOH ayırma yapmak 3rdparty kütüphaneleri kullanan pek çok uygulamaları vardır. Örneğin, hatta Microsoft'un kendi PAZARLAR LOH her zaman heck parçaları "yeni Texture2D()" veya "Doku.() FromFile" herhangi bir ilaç olmadan!

Eğer öyleyse oluşturmak için çalışıyorsanız, bir "an". Oyun Motoru NET bir gerçek boyun ağrısı, bizim LOH herhangi bir şekilde olmadan bellek sızıntısı durdurmak için. Yapabileceğimiz tek şey. "" "" ve PAZARLAR. unut kendi kütüphanemizi yapmaya karar verdiğimiz sürece, yavaş Elbette bu Microsoft istemiyor!

Baş ağrısı aylar bize (ve diğerleri!) çözülmüş olurdu eğer MS bu sadece bir yöntem ile bize vermek isterseniz; yine söyleyeceğim:

GC.CompactLargeObjectHeap()

Ve bu öneri vermeye çalışıyorum, MS bunu bir adım daha ileri götürüp, bu komut izin öneririm:

GC.DoLargeObjectHeapCompactionWhenOutOfMemory = true;   // would be false by default

Sadece "Visual3D, Oyun Motoru parçalanma ilk OOM istisna .neden olduğunda" (ürün), ve daha sonra otomatik olarak, gerçek bu set edelim diye NET otomatik olarak LOH kompakt ve tahsisi yeniden deneyin!

Vay be, şimdi hepsi ile uyumlu olur .NET abartılmış "işe yarıyor" ve "kullanımı kolay"... ve tek neden bu "performans vurmak" için aşırı durumlarda, alternatif OOM çarpışma, zorlama bir yeniden uygulama!

Microsoft -- bunu bizim için yap lütfen!

< / ^ hr .

"Kullanmak daha iyi bellek yönetimi" -- Evet! basmakalıp saf tavsiyesi diyerek cehaletin ilan etmeyin lütfen Bu çok uygunsuz bir tavsiye! Ayrıca söylemek zorunda kalacak "kendi 3rdparty kütüphaneleri yazma" (örneğin JAY)!!!!

Neden Microsoft zaten bu davranış sağlanan değil .???NET? Ne zararı olacak ki? En iyi ihtimalle "bellek sızıntısı" ama hiç bir zaman tam olarak onları düzeltmek. aşağı yavaş olabilir bu çok sinir bozucu ve zaman alıcı bir yara bandı çözüm, bizi kurtaracak diye

Talep ettiğimiz çözüm kullanmak istemiyorum olanlar için zararsız olurdu, ve gerçekten kullanmak ister olanlar için ferahlatıcı bir kurtuluş sağlar. Lütfen, lütfen, Lütfen, bu sağlar .NET 4.0 .

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Dopelives

    Dopelives

    30 Temmuz 2009
  • Krumme1996

    Krumme1996

    21 EYLÜL 2009
  • newreleaseblitz

    newreleasebl

    13 Ocak 2010