GC.Collect () kullanmanın nesi yanlış?


103

Bu işlevle oynamanın ciddi sonuçlarını anlasam da (ya da en azından düşündüğüm budur), neden saygın programcıların, bilmeyenlerin bile kullanmayacağı şeylerden biri haline geldiğini anlamıyorum. bu ne için.

Diyelim ki, bellek kullanımının kullanıcının ne yaptığına bağlı olarak son derece değiştiği bir uygulama geliştiriyorum. Uygulama yaşam döngüsü iki ana aşamaya ayrılabilir: düzenleme ve gerçek zamanlı işleme. Düzenleme aşamasında milyarlarca hatta trilyonlarca nesnenin yaratıldığını varsayalım; bazıları küçük, bazıları değil, bazılarının sonlandırıcıları olabilir ve bazılarının olmayabilir ve ömürlerinin birkaç milisaniyeden uzun saate kadar değiştiğini varsayar. Ardından, kullanıcı gerçek zamanlı aşamaya geçmeye karar verir. Bu noktada, performansın temel bir rol oynadığını ve program akışındaki en ufak bir değişikliğin feci sonuçlar doğurabileceğini varsayalım. Nesne oluşturma daha sonra nesne havuzları ve benzerleri kullanılarak mümkün olan en aza indirilir, ancak daha sonra GC beklenmedik bir şekilde çalar ve hepsini atar ve biri ölür.

Soru: Bu durumda, ikinci aşamaya geçmeden önce GC.Collect () 'i çağırmak akıllıca olmaz mı?

Sonuçta, bu iki aşama asla birbiriyle çakışmaz ve GC'nin toplayabileceği tüm optimizasyon ve istatistikler burada çok az işe yarar ...

Not: Bazılarınızın da belirttiği gibi, .NET böyle bir uygulama için en iyi platform olmayabilir, ancak bu, bu sorunun kapsamı dışındadır. Amaç, bir GC.Collect () çağrısının bir uygulamanın genel davranışını / performansını iyileştirip iyileştiremeyeceğini açıklığa kavuşturmaktır. Böyle bir şeyi yapacağınız koşulların son derece nadir olduğu konusunda hepimiz hemfikiriz, ancak yine de, GC tahmin etmeye çalışır ve çoğu zaman mükemmel şekilde yapar, ancak yine de tahminle ilgilidir.

Teşekkürler.


24
"programın akışındaki en ufak bir değişiklik feci sonuçlar doğurabilir ... birisi ölebilir" - C # .NET'in sizin amaçlarınız için yeterince belirleyici olduğundan emin misiniz?
Steve Jessop

4
Windows veya .NET gerçek zamanlı platformlar değildir ve bu nedenle performans ölçütlerini garanti edemezsiniz, en azından insan hayatını riske atacak kadar değil. Abarttığın ya da dikkatsiz olduğun konusunda herkese katılıyorum.
Sergio Acosta

3
"Saygın programcıların, ne işe yaradığını bile bilmeyenlerin bile kullanmayacağı bu şeylerden birinde" LOL! Nedenini bilmeden şeyler kullanan programcılar, benim kitabımda pek saygın değildir. :)
The Dag

Yanıtlar:


87

Rico'nun Blogundan ...

Kural 1

Yapma.

Bu gerçekten en önemli kuraldır. GC.Collect () 'in çoğu kullanımının kötü bir fikir olduğunu söylemek doğru olur ve bunu orjinal gönderide biraz detaylı olarak ele aldım, bu yüzden burada hepsini tekrar etmeyeceğim. Öyleyse devam edelim ...

2. Kural

Tekrar etmeyen bir olay meydana geldiyse ve bu olay büyük olasılıkla çok sayıda eski nesnenin ölmesine neden olmuşsa GC.Collect () 'i çağırmayı düşünün.

Bunun klasik bir örneği, bir istemci uygulaması yazıyorsanız ve kendisiyle ilişkili birçok veriye sahip çok büyük ve karmaşık bir form görüntülemenizdir. Kullanıcınız bu formla etkileşime girerek potansiyel olarak bazı büyük nesneler oluşturdu ... XML belgeleri gibi şeyler veya büyük bir DataSet veya iki. Form kapandığında bu nesneler ölür ve bu nedenle GC.Collect () onlarla ilişkili hafızayı geri kazanır ...

Öyleyse, bu durum Kural 2'nin kapsamına girebilir gibi görünüyor, zaman içinde birçok eski nesnenin öldüğü ve tekrar etmediği bir an olduğunu biliyorsunuz. Ancak Rico'nun ayrılık sözlerini unutmayın.

1. Kural, güçlü kanıtlar olmadan 2. Kuralın önüne geçmelidir.

Ölçün, ölçün, ölçün.


9
Bunun sadece eski bir şey olduğunu söyleyebilirim. Ne yaptığınızı biliyorsanız ve bu nedenle ne zaman ve nasıl yapılacağını ve yan etkilerini biliyorsanız, hiçbir şey gerçekten kötü veya tehlikeli değildir. Asla yapma, asla xxxx kullanma gibi şeyler, dünyayı kötü programcılardan korumak için oraya konur: D
Jorge Córdoba


GC.Collect kullanmanın iyi bir uygulama olduğunu söylemiyorum. Ancak bazen gerçek nedenini bilmeden sorunları çözmenin hızlı bir yoludur. Çirkin, biliyorum ama işe yarıyor ve bana kötü bir yaklaşım değil gibi geliyor, özellikle sorunun temel nedenini bulmak için fazla zaman olmadığında ve patronun arkanızda duruyorsa ... bilirsiniz.
Sessiz Sojourner

58

Üretim kodunda GC.Collect () 'i çağırırsanız, aslında GC'nin yazarlarından daha fazlasını bildiğinizi beyan etmiş olursunuz. Durum bu olabilir. Ancak genellikle değildir ve bu nedenle kesinlikle önerilmez.


3
Bu çok doğru, ancak tüm gelişmeler için geçerli varsayımlar yapıp yapamayacaklarını bilmiyorum.
MasterMastic

2
@Ken Hayır, yapamazlar. Ama bunu yapmak için daha iyi bir konumda mısınız? Yoksa belirli bir donanım, belirli bir işletim sistemi sürümü vb. Varsayarak kod yazacak mısınız? Acı / kazanç oranı bunda çok yüksek.
Dag

2
@TheDag IMO tabii ki öyleyim. Belleği serbest bıraktığımda ve ne olursa olsun, donanımı gerçekten umursamıyorum çünkü bununla başa çıkmak OS işi. İşletim sistemini de umursamıyorum çünkü programladığım tüm arayüzler için ortak bir arayüzüm var. (örneğin Windows, Mac veya Linux olması umurumda değil: C / C ++ 'da bellek ayırırken / serbest bırakırken, yeni / delete malloc / dealloc). Her zaman yanılabilirim, bu yüzden beni düzeltmekten çekinmeyin.
MasterMastic

@MasterMastic mallocyalnızca çok basit bir arayüze sahiptir ve uygulamaları önemli ölçüde değişiklik gösterebilir. Her şey ne tür bir sorunu çözmeye çalıştığınıza bağlı. Eğer malloc"yeterince iyi" olduğunu, onunla çıkacağını, havuzu tampon gerek olmaz? C / C ++ geliştirme, daha iyi bildiğiniz için (ve bazen gerçekten yaparsınız) işletim sistemi / çalışma zamanı / kitaplıkları ikinci kez tahmin etmeye çalıştığınız örneklerle doludur . Performans açısından kritik birçok uygulama, sistem / çalışma zamanı ayırıcılarını kullanmaktan tamamen kaçınır. Başlangıçta tüm belleği önceden ayırmak için kullanılan oyunlar (sabit boyutlu diziler vb.).
Luaan

24

Peki, .NET'ten MS Word veya MS Excel gibi COM nesnelerini kullanmaya ne dersiniz? GC.CollectCOM nesnelerini serbest bıraktıktan sonra arama yapmadan , Word veya Excel uygulama örneklerinin hala var olduğunu gördük.

Aslında kullandığımız kod şudur:

Utils.ReleaseCOMObject(objExcel)

' Call the Garbage Collector twice. The GC needs to be called twice in order to get the
' Finalizers called - the first time in, it simply makes a list of what is to be finalized,
' the second time in, it actually does the finalizing. Only then will the object do its 
' automatic ReleaseComObject. Note: Calling the GC is a time-consuming process, 
' but one that may be necessary when automating Excel because it is the only way to 
' release all the Excel COM objects referenced indirectly.
' Ref: http://www.informit.com/articles/article.aspx?p=1346865&seqNum=5
' Ref: http://support.microsoft.com/default.aspx?scid=KB;EN-US;q317109
GC.Collect()
GC.WaitForPendingFinalizers()
GC.Collect()
GC.WaitForPendingFinalizers()

Öyleyse bu, çöp toplayıcının yanlış kullanımı olur mu? Öyleyse, Interop nesnelerinin ölmesini nasıl sağlarız? Böyle kullanılacak anlamına gelmez Ayrıca, neden olduğu GCbireyin Collectyöntem bile Public?


3
Bu harika bir yeni StackOverflow sorusu olur, yani: GC'yi çağırmadan COM örneklerini nasıl ortadan kaldırılır. Yönetilmeyen döngüsel referanslarla ilgili olarak. Bu, beni VB6 Outlook eklentimi C # sürümüne yükseltme konusunda endişelendiren zorluklardan biri. (COM referanslarının artık ihtiyaç duyulmadığında deterministik bir şekilde öldürülmesini garanti eden VB tarafında kodlama kalıpları ve test senaryoları geliştirmek için çok çalışma yaptık).
rkagerer

2
Bu genel olarak COM nesneleri için geçerliyse, belki bu geçerli bir senaryodur. Ancak, sorunun muhtemelen bir COM sunucusu olarak etkileşimli bir masaüstü için tasarlanmış bir istemci uygulaması kullanıyor olmanızdan kaynaklandığını söyleyebilirim. MSDN bilgi tabanından: "Microsoft şu anda herhangi bir katılımsız, etkileşimli olmayan istemci uygulamasından veya bileşeninden (ASP, ASP.NET, DCOM ve NT Hizmetleri dahil) Microsoft Office uygulamalarının Otomasyonunu önermiyor ve desteklemiyor çünkü Office Office bu ortamda çalıştırıldığında istikrarsız davranış ve / veya kilitlenme sergileyebilir. "
The Dag

2
@TheDag - Microsoft bunu önermeyebilir, ancak çoğumuz eski VB6 kodunu ofis birlikte çalışarak .Net Windows uygulamalarına taşımak zorunda kaldık. Büyük bir VB6'dan .Net'e dönüştürme projesi için tüm görünmez asılı referanslardan nihayet kurtulana kadar aylarca çalıştım. Ters atama sırasına göre yayınlamayı öğrenmek ve koleksiyonlar da dahil olmak üzere HER tek com nesnesine yerel referansları tutmak yardımcı oldu.
Dib

15

GC, aşk / nefret ilişkim olan şeylerden biri. Bunu geçmişte VistaDB aracılığıyla kırdık ve bununla ilgili blog yazdık. Bunu düzelttiler, ancak bunlardan böyle şeylerin düzeltilmesi UZUN zaman alıyor.

GC karmaşıktır ve herkese uyan tek bir yaklaşım bu kadar büyük bir şey için çok ama çok zor. MS oldukça iyi bir iş çıkardı, ancak zaman zaman GC'yi kandırmak mümkün.

Genel Collectolarak, bir ton belleği boşalttığınızı bilmediğiniz sürece bir eklememelisiniz ve eğer GC onu şimdi temizlemiyorsa orta yaşam krizine girecektir.

Bir dizi kötü GC.Collectifadeyle tüm makineyi alt üst edebilirsiniz . Bir toplama ifadesine duyulan ihtiyaç neredeyse her zaman daha büyük bir temel hataya işaret eder. Bellek sızıntısı genellikle referanslarla ve nasıl çalıştıklarına dair anlayış eksikliğiyle ilgilidir. Veya IDisposableihtiyaç duymayan nesnelerin kullanılması ve GC'ye çok daha fazla yük binmesi.

Sistem performans sayaçları aracılığıyla GC'de harcanan sürenin yüzdesini yakından izleyin. Uygulamanızın GC'de zamanının% 20'sini veya daha fazlasını kullandığını görürseniz, ciddi nesne yönetimi sorunlarınız (veya anormal bir kullanım modeli) var demektir. Tüm uygulamanızı hızlandıracağı için GC'nin harcadığı zamanı her zaman en aza indirmek istersiniz.

Ayrıca, GC'nin sunucularda iş istasyonlarından farklı olduğuna dikkat etmek önemlidir. Her ikisini de test etmeyen (ya da onların ikisi olduğunun bile farkında olmayan) insanlarla ilgili sorunları tespit etmenin çok zor olduğunu gördüm.

Ve cevabımı olabildiğince eksiksiz hale getirmek için, o platformu da hedefliyorsanız, Mono altında da test etmelisiniz. Tamamen farklı bir uygulama olduğu için MS uygulamasından tamamen farklı sorunlar yaşayabilir.


Suçlu genellikle olaylardır. Bir olay işleyici olarak bir örnek yöntemi kullanıldığında, olayın yayıncısının, olay temsilcisi aracılığıyla aboneye bir referansı vardır. Bundan kaynaklanan sorunları önlemenin tek "kolay" yolu, yalnızca aboneler kadar uzun ömürlü olan yayıncıları kullanmaktır (örneğin, metin kutusu olması gerekmediğinden, içeren form tarafından işlenen bir etkinliği yayınlayan bir TextBox sorun değildir. formun dışında yaşamak). Örnek problem senaryosu: Singleton modeli, model olaylarını işleyen geçici görünümler.
Dag

5
Tüm makineyi nasıl mahvedebiliriz?
Adam R. Gray

13

Yararlı olduğu durumlar vardır, ancak genel olarak bundan kaçınılmalıdır. Bunu GOTO ile veya bir mopedle karşılaştırabilirsiniz: ihtiyacınız olduğunda yaparsınız, ancak arkadaşlarınıza bundan bahsetmezsiniz.


12

Deneyimlerime göre, üretim kodunda GC.Collect () 'e bir çağrı yapılması asla tavsiye edilmedi. Hata ayıklamada, evet, olası bellek sızıntılarını netleştirmeye yardımcı olmak için avantajları vardır. Sanırım temel nedenim, GC'nin programcılar tarafından benden çok daha akıllıca yazılmış ve optimize edilmiş olmasıdır ve eğer GC.Collect () 'i çağırmam gerektiğini hissettiğim bir noktaya gelirsem, bu yoldan çıktığımın bir ipucudur. bir yerde. Sizin durumunuzda, aslında hafıza sorunlarınız varmış gibi görünmüyor, sadece koleksiyonun sürecinize nasıl bir istikrarsızlık getireceğiyle ilgileniyorsunuz. Halen kullanımda olan nesneleri temizlemeyeceğini ve hem artan hem de alçalan taleplere çok çabuk adapte olduğunu görünce, bunun için endişelenmenize gerek kalmayacağını düşünürdüm.


10

GC.Collect () 'i çağırmanın en büyük nedenlerinden biri, tanımladığınız gibi çok fazla çöp oluşturan önemli bir olayı gerçekleştirmiş olmanızdır. GC.Collect () 'i çağırmak burada iyi bir fikir olabilir; aksi takdirde, GC bunun "tek seferlik" bir olay olduğunu anlayamayabilir.

Tabii ki profilini çıkarmalı ve kendiniz görmelisiniz.


9

Açıkçası, gerçek zamanlı olmayan çöp toplama dillerinde gerçek zamanlı gereksinimleri olan kod yazmamalısınız.

İyi tanımlanmış aşamaları olan bir durumda, çöp toplayıcıyı tetiklemede sorun yoktur. Ancak bu durum oldukça nadirdir. Sorun şu ki, birçok geliştirici bunu kült tarzı bir kağıt üzerine kağıt problemi için kullanmaya çalışacak ve bunu fark gözetmeden eklemek performans sorunlarına neden olacaktır.


Doğru. Ancak, "nesne çöp toplama için uygun değil, ancak olmalıdır" hata koşulunu yakalayabilen otomatik testler değerli olacaktır. Bu, fabrika mantığı, yıkıcı mantık ve GC.Collect'in bir kombinasyonu yoluyla elde edilebilir. Örneğin, Varlık sınıfınızın bir IObjectTracker özelliği vardır, normalde boştur, ancak test amaçlı varlık fabrikası tarafından atanır. Fabrika ayrıca nesnenin doğumunu izleyiciye bildirirken, yıkıcı (mevcut olduğunda) ona ölüm bildirir. "Yıkıcının tüm çöp-toplanabilir nesneler için çalıştırıldığını" bilirseniz, sızıntıları tespit etmek için izleyici durumunu kontrol edebilirsiniz.
The Dag

7

GC.Collect () çağrısı, CLR'yi, her bir nesnenin referansları kontrol ederek gerçekten serbest bırakılıp bırakılamayacağını görmek için yığın yürüyüşü yapmaya zorlar. Bu, nesnelerin sayısı yüksekse ve ayrıca çöp toplamayı çok sık tetiklediği biliniyorsa ölçeklenebilirliği etkileyecektir. CLR'ye güvenin ve uygun olduğunda çöp toplayıcının kendi kendine çalışmasına izin verin.


2
Yalnızca yığının yürümesine neden olmazsınız, aynı zamanda uygulamalarınızın ana iş parçacığı (ve oluşturduğu tüm alt iş parçacıkları), GC'nin yığını yürütebilmesi için dondurulur . Uygulamanız GC'de ne kadar çok zaman geçirirse donmuş halde o kadar çok zaman geçirir.
Scott Dorman

3
Yavaş performanstan ziyade Yetersiz Bellek istisnası nedeniyle Uygulama Çökmesi konusunda daha çok endişeliyim çünkü uygulama / GC artık ihtiyaç duyulmayan şeyleri atıyordu. Microsoft'un neden FIRST çöpü atmadan bir OOM istisnası attığını bilen var mı? (Bu OBVIOUS adımı olmadan - ya da en azından bu adımın OOM istisnasını atmadan önce neden denenmediğine dair bir açıklama olmadan, olayların "otomatik olarak" olması gerektiği gibi "gerçekleşeceğine dair herhangi bir inancım olduğundan emin değilim.
Wonderbird

6

Aslında, GC.Collect'i çağırmanın çok kötü bir uygulama olduğunu düşünmüyorum.
Buna ihtiyaç duyduğumuz durumlar olabilir. Örneğin, bir iş parçacığım çalıştıran, bir veritabanında farklı tabloları açan, bir BLOB alanındaki içerikleri geçici bir dosyaya çıkaran, dosyayı şifreleyen, ardından dosyayı ikili akışa okuyup tekrar bir BLOB'a okuyan bir formum var. başka bir tablodaki alan.

İşlemin tamamı oldukça fazla bellek alır ve tablolardaki satır sayısı ve dosya içeriğinin boyutu hakkında kesin bilgi yoktur.

Eskiden OutofMemory Exception'ı sık sık alırdım ve GC.Collect'i bir sayaç değişkenine göre periyodik olarak çalıştırmanın akıllıca olacağını düşündüm. Bir sayacı arttırıyorum ve belirli bir seviyeye ulaşıldığında, GC oluşmuş olabilecek herhangi bir çöpü toplamak ve öngörülemeyen bellek sızıntıları nedeniyle kaybedilen herhangi bir belleği geri almak için çağrılır.

Bundan sonra, iyi çalıştığını düşünüyorum, en azından istisna yok !!!
Ben şu şekilde arıyorum:

var obj = /* object utilizing the memory, in my case Form itself */
GC.Collect(GC.GetGeneration(obj ,GCCollectionMode.Optimized).

5

.Net altında, bir çöp toplama işlemi gerçekleştirmek için gereken süre, çöp olmayan şeylerin miktarından çok daha güçlü bir şekilde ilişkilidir. Aslında, bir nesne geçersiz kılmadıkça Finalize(açıkça veya C # yıkıcı aracılığıyla), WeakReferencea'nın hedefi olmadıkça , Büyük Nesne Yığını üzerinde bulunmadıkça veya başka bir gc ile ilgili şekilde özel olmadığı sürece, içinde bulunduğu belleği tanımlayan tek şey bir nesne olarak ona yönelik köklü referansların varlığıdır. Aksi takdirde, GC'nin çalışması, bir binadan değerli olan her şeyi alıp binayı dinamize etmeye, eskisinin yerine yenisini inşa etmeye ve tüm değerli eşyaları içine koymaya benzer. Binayı dinamitlemek için gereken çaba, içindeki çöp miktarından tamamen bağımsızdır.

Sonuç olarak, arama GC.Collect, sistemin yapması gereken toplam iş miktarını artırma eğilimindedir. Bir sonraki koleksiyonun oluşumunu geciktirecek, ancak büyük olasılıkla bir sonraki koleksiyon gerçekleştiğinde gerekeceği kadar işi hemen yapacak; Bir sonraki toplama meydana gelmiş olurdu noktada toplam süre toplama etmişti hemen aynı olmuş olacak harcanan GC.Collecter vardı daha gerekli olan başarılı koleksiyonu neden çağrılmadı, ancak sistem bazı çöp birikmiş olacak GC.Collectdeğil çağrıldı.

GC.CollectGerçekten yararlı olduğunu görebildiğim zamanlar , bir kodun bellek kullanımını ölçmek gerektiğinde (çünkü bellek kullanım rakamları yalnızca bir koleksiyonun ardından gerçekten anlamlıdır) veya birkaç algoritmadan hangisinin daha iyi olduğunu (GC.Collect () çağırmak) birkaç kod parçasının her birini çalıştırmadan önce tutarlı bir temel durum sağlanmasına yardımcı olabilir). Bir kişinin GC'nin bilmediği şeyleri bildiği birkaç başka durum da vardır, ancak tek iş parçacıklı bir program yazmadıkça, GC.Collectbir iş parçacığının veri yapılarının "orta yaş krizini" önlemesine yardımcı olacak bir çağrının bilinmesinin hiçbir yolu yoktur. "diğer iş parçacığı verilerinin, aksi takdirde önlenecek olan" orta yaş krizlerine "neden olmadı.


5

Bir döngüde görüntü oluşturma - dispose'ı çağırsanız bile, bellek kurtarılmaz. Her seferinde çöp toplanıyor. Fotoğraf işleme uygulamamda 1,7 GB bellekten 24 MB'a geçtim ve performans mükemmel.

GC.Collect'i aramanız gereken kesinlikle zaman vardır.


2
Arama Disposeolduğu gerekiyordu yönetilen bellek bırakın. .NET'teki bellek modelinin nasıl çalıştığını bilmiyor gibisiniz.
Andrew Barber

4

Çöp toplayıcının çöp toplamaması ve hafızayı boşaltmasıyla benzer bir sorun yaşadık.

Programımızda, bazı mütevazı boyutlu Excel Elektronik Tablolarını OpenXML ile işliyorduk. Elektronik tablolar, yaklaşık 1000 satırlık 14 sütuna sahip 5 ila 10 "sayfa" içeriyordu.

32 bit ortamdaki (x86) program "yetersiz bellek" hatasıyla çökebilir. Bunu x64 ortamında çalıştırmayı başardık, ancak daha iyi bir çözüm istedik.

Bir tane bulduk.

Burada neyin işe yaramadığına ve atılan nesnelerden belleği boşaltmak için açıkça Çöp Toplayıcıyı çağırmaya gelince neyin işe yaradığına dair bazı basitleştirilmiş kod parçaları verilmiştir.

Alt programın içinden GC'yi çağırmak işe yaramadı. Hafıza asla geri kazanılmadı ...

For Each Sheet in Spreadsheets
    ProcessSheet(FileName,sheet)
Next

Private Sub ProcessSheet(ByVal Filename as string, ByVal Sheet as string)
    ' open the spreadsheet 
    Using SLDoc as SLDocument = New SLDocument(Filename, Sheet)
        ' do some work....
        SLDoc.Save
    End Using
    GC.Collect()
    GC.WaitForPendingFinalizers()
    GC.Collect()
    GC.WaitForPendingFinalizers()
End Sub

GC çağrısını alt yordamın kapsamının dışına taşıyarak, çöp toplandı ve bellek serbest bırakıldı.

For Each Sheet in Spreadsheets
    ProcessSheet(FileName,sheet)
    GC.Collect()
    GC.WaitForPendingFinalizers()
    GC.Collect()
    GC.WaitForPendingFinalizers()
Next

Private Sub ProcessSheet(ByVal Filename as string, ByVal Sheet as string)
    ' open the spreadsheet 
    Using SLDoc as SLDocument = New SLDocument(Filename, Sheet)
        ' do some work....
        SLDoc.Save
    End Using
End Sub

Umarım bu, çağrıları görmezden geliyor gibi göründüğünde .NET çöp toplama konusunda hayal kırıklığına uğramış diğer kişilere yardımcı olur GC.Collect().

Paul Smith


4

Açıkça bir koleksiyon çağrısı yapmak yanlış değildir. Bazı insanlar, satıcı tarafından sağlanan bir hizmetse sorgulamayın gerçekten inanmak ister. Oh, ve interaktif uygulamanızın yanlış anlarında tüm bu rastgele donmalar? Bir sonraki sürüm daha iyi hale getirecek!

Bir arka plan sürecinin bellek manipülasyonuyla ilgilenmesine izin vermek, bununla kendimiz ilgilenmek zorunda olmamak anlamına gelir, doğru. Ancak bu mantıksal olarak, her koşulda kendimiz bununla başa çıkmamamızın en iyisi olduğu anlamına gelmez. GC çoğu durum için optimize edilmiştir. Ancak bu, mantıksal olarak her durumda optimize edildiği anlamına gelmez.

Hiç kesin bir cevapla 'en iyi sıralama algoritması hangisi' gibi açık bir soruyu yanıtladınız mı? Eğer öyleyse, GC'ye dokunmayın. Koşulları soran veya 'bu durumda' tipi cevaplar verenleriniz için, GC'yi ve ne zaman etkinleştireceğinizi öğrenmeye devam edebilirsiniz.

Söylemeliyim ki, Chrome ve Firefox'ta beni hayal kırıklığına uğratan uygulama donmaları yaşadım ve o zaman bile bazı durumlarda bellek engellenmeden büyüyor - Keşke çöp toplayıcıyı aramayı öğrenirlerse - veya bana bir düğmesine basıp bir sayfanın metnini okumaya başladığımda ona vurabilirim ve böylece önümüzdeki 20 dakika boyunca donmadan kurtulabilirim.


2

Senaryo konusunda haklı olduğunu düşünüyorum, ancak API konusunda emin değilim.

Microsoft, bu gibi durumlarda , GC'ye yakında bir koleksiyon gerçekleştirmesi gerektiğine dair bir ipucu olarak bellek baskısı eklemeniz gerektiğini söylüyor .


2
İlginç, ancak belgeler AddMemoryPressure'un 'küçük bir yönetilen nesne büyük miktarda yönetilmeyen bellek ayırdığında' kullanılması gerektiğini söylüyor. (benim vurgu)
Robert Paulson

2

Bunun nesi var? Çöp toplayıcıyı ve bellek ayırıcıyı ikinci kez tahmin ettiğiniz gerçeği, bunlar arasında uygulamanızın çalışma zamanında gerçek bellek kullanımı hakkında sizden çok daha fazla fikir vardır.


1
Çöp toplayıcının sezgisel doğası ve bu işlevselliği dış dünyaya göstermiş olmaları, olması gerektiği yerde kullanıldığında faydalı olacak bir şey olarak düşünmeme neden oluyor. Sorun onu kullanmak değil, nasıl, nerede ve ne zaman kullanacağını bilmektir.
Tuzak

GC'lerin diğer tüm uygulamalar ve hafıza ihtiyaçları hakkında daha iyi bilgilerinden bahsetmiyorum bile . GC, işletim sistemi ile bellek üzerinde anlaşır ve bu nedenle kullanılabilir fiziksel bellekten ve makinedeki hem yönetilen hem de yönetilmeyen diğer tüm işlemlerden etkilenir. Genel Kurul'un "duruma göre" "toplama yapmak için ne zaman iyi bir zaman olduğunu" gerçekten bildiğinden şüphem olsa da, genel olarak HERHANGİ BİR uygulamadan daha iyi bir stratejiye sahip olma olasılığı çok yüksektir. ;)
The Dag

2

GC.Collect () 'i çağırma arzusu genellikle başka bir yerde yaptığınız hataları örtmeye çalışıyor!

Artık ihtiyaç duymadığınız şeyleri atmayı unuttuğunuz yeri bulmanız daha iyi olur.


5
bu belki bir genelleme
MickyD

1

Sonuç olarak, uygulamanın profilini çıkarabilir ve bu ek koleksiyonların işleri nasıl etkilediğini görebilirsiniz. Profiline girmediğiniz sürece ondan uzak durmanızı öneririm. GC, kendi kendine bakmak üzere tasarlanmıştır ve çalışma zamanı geliştikçe verimliliği artırabilirler. Çalışmaları bozabilecek ve bu iyileştirmelerden yararlanamayacak bir sürü kodun ortalıkta dolaşmasını istemezsiniz. For yerine foreach'i kullanmak için benzer bir argüman var, bu, kapakların altındaki gelecekteki iyileştirmelerin foreach'a eklenebileceği ve kodunuzun bundan yararlanmak için değiştirilmesi gerekmediği.


1

.NET Framework'ün kendisi hiçbir zaman gerçek zamanlı bir ortamda çalışacak şekilde tasarlanmamıştır. Gerçek zamanlı işlemeye gerçekten ihtiyacınız varsa, ya .NET tabanlı olmayan katıştırılmış gerçek zamanlı bir dil kullanırsınız ya da bir Windows CE aygıtında çalışan .NET Compact Framework kullanırsınız.


Gerçek zamanlı ortamlar için tasarlanmış olan .Net Micro Framework'ü kullanıyor olabilir.
TraumaPony

@TraumaPony: Bu sayfanın altındaki tabloyu kontrol edin msdn.microsoft.com/en-us/embedded/bb278106.aspx : Açıkçası, Micro Framework gerçek zamanlı ortamlar için tasarlanmamıştır. Bununla birlikte, gömülü ortamlar (WinCE gibi) için tasarlanmıştır, ancak daha düşük güç gereksinimleri vardır.
Scott Dorman

1

Yapacağı en kötü şey, programınızın bir süre donmasını sağlamaktır. Yani senin için uygunsa, yap. Genellikle kullanıcı etkileşimine sahip yoğun istemci veya web uygulamaları için gerekli değildir.

Bazen uzun süre çalışan iş parçacıkları veya toplu iş programları olan programların, nesneleri düzgün bir şekilde elden çıkarıyor olsalar bile OutOfMemory istisnası alacağını buldum. Hatırladığım bir tanesi bir iş kolu veritabanı işlem işlemiydi; diğeri, kalın bir istemci uygulamasında bir arka plan iş parçacığı üzerinde bir dizin oluşturma rutiniydi.

Her iki durumda da sonuç basitti: Sürekli olarak hafızanın dışında GC.Collect yok; GC.Collect, kusursuz performans.

Hafıza sorunlarını birkaç kez çözmeyi denedim, boşuna. Ben çıkardım.

Kısacası, hata almadığınız sürece onu yerleştirmeyin. Takarsanız ve bellek sorununu çözmezse, tekrar çıkarın. Serbest Bırakma modunda test etmeyi ve elmaları elmalarla karşılaştırmayı unutmayın.

Bunda bir şeylerin ters gidebileceği tek zaman, bu konuda ahlaklı olduğunuz zamandır. Bu bir değerler sorunu değil; birçok programcı öldü ve kodlarında birçok gereksiz GC.Collects ile doğrudan cennete gitti, bu da onları geride bıraktı.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.