Hata ayıklama ve yayın sürümleri arasındaki performans farklılıkları


280

İtiraf etmeliyim ki, genellikle programımdaki Hata Ayıkla ve Bırak yapılandırmaları arasında geçiş yapma zahmetine girmedim ve programlar gerçekten müşterilerin yerine yerleştirildiğinde bile Hata Ayıklama yapılandırmasına gitmeyi tercih ettim .

Gibi bildiğim kadarıyla bu modeller arasındaki tek fark kırpma işlemini olmasıdır değiştirmezseniz ayıklama sahip DEBUGtanımlanmış sabit ve Yayın sahip Optimize kod denetlenen.

Yani sorularım aslında iki yönlü:

  1. Bu iki yapılandırma arasında çok fazla performans farkı var mı? Burada performansta büyük farklılıklara neden olacak belirli bir kod türü var mı, yoksa aslında önemli değil mi?

  2. Sürüm yapılandırması altında başarısız olabilecek Hata Ayıklama yapılandırması altında düzgün çalışacak herhangi bir kod türü var mı veya Hata Ayıklama yapılandırması altında sınanmış ve düzgün çalışan kodun Sürüm yapılandırması altında da iyi çalışacağından emin olabilirsiniz.


Yanıtlar:


511

C # derleyicisi yayımlanmış IL'yi Release derlemesinde çok fazla değiştirmez. Dikkat çeken şey, artık kıvırcık bir küme üzerinde bir kesme noktası ayarlamanıza izin veren NOP opcodlarını yaymamasıdır. Büyük olan, JIT derleyicisine yerleştirilmiş eniyileştiricidir. Aşağıdaki optimizasyonları yaptığını biliyorum:

  • Yöntem satır içi. Bir yöntem çağrısı, yöntemin kodunun enjekte edilmesi ile değiştirilir. Bu büyük bir özelliktir, mülk erişimcilerini esasen ücretsiz hale getirir.

  • CPU kayıt tahsisi. Yerel değişkenler ve yöntem bağımsız değişkenleri, yığın karesine hiç (veya daha az sıklıkta) depolanmadan CPU kaydında saklanabilir. Bu büyük bir, hata ayıklama optimize kod çok zor hale getirmek için dikkate değer. Ve uçucu anahtar kelimeye bir anlam vermek.

  • Dizi dizini denetiminin kaldırılması. Dizilerle çalışırken önemli bir optimizasyon (tüm .NET koleksiyonu sınıfları dahili olarak bir dizi kullanır). JIT derleyicisi, bir döngünün bir diziyi hiçbir zaman sınırların dışında dizine eklemediğini doğrulayabildiğinde, dizin denetimini ortadan kaldırır. Büyük olan.

  • Döngü açma. Küçük gövdeli döngüler, kodu vücutta 4 kata kadar tekrarlayıp daha az döngü yaparak geliştirilir. Şube maliyetini azaltır ve işlemcinin süper skaler yürütme seçeneklerini iyileştirir.

  • Ölü kod ortadan kaldırılması. İf (false) {/ ... /} gibi bir deyim tamamen ortadan kaldırılır. Bu, sürekli katlama ve eğim nedeniyle oluşabilir. Diğer durumlarda, JIT derleyicisinin kodun olası bir yan etkisi olmadığını belirleyebildiği yerdir. Bu optimizasyon, profil oluşturma kodunu bu kadar zor yapan şeydir.

  • Kod kaldırma. Döngüden etkilenmeyen bir döngü içindeki kod döngüden çıkarılabilir. Bir C derleyicisinin optimize edicisi, kaldırma fırsatları bulmak için çok daha fazla zaman harcayacaktır. Bununla birlikte, gerekli veri akışı analizi nedeniyle pahalı bir optimizasyondur ve titreşim zamanı karşılayamaz, bu nedenle sadece bariz vakaları kaldırır. .NET programcılarını daha iyi kaynak kodu yazmaya ve kendilerini kaldırmaya zorlama.

  • Ortak alt ifade eliminasyonu. x = y + 4; z = y + 4; z = x olur; Dest [ix + 1] = src [ix + 1] gibi ifadelerde oldukça yaygındır; yardımcı değişken girmeden okunabilirlik için yazılmıştır. Okunabilirlikten taviz vermenize gerek yok.

  • Sabit katlama. x = 1 + 2; x = 3 olur; Bu basit örnek derleyici tarafından erken yakalanır, ancak diğer optimizasyonların bunu mümkün kıldığı JIT zamanında olur.

  • Kopya yayılımı. x = a; y = x; y = a olur; Bu, kayıt tahsisatörünün daha iyi kararlar almasına yardımcı olur. Bu, x86 titreşiminde büyük bir anlaşma çünkü çalışmak için çok az kaydı var. Doğru olanları seçmek mükemmel olmak için çok önemlidir.

Bunlar, örneğin uygulamanızın Hata Ayıklama derlemesini profillediğinizde ve Sürüm derlemesiyle karşılaştırdığınızda büyük fark yaratabilecek çok önemli optimizasyonlardır . Bu sadece kod kritik yolunuzdayken gerçekten önemlidir, yazdığınız kodun% 5 ila 10'u aslında programınızın performansını etkiler. JIT optimizer ne kritik ön bilmek yeterince akıllı değil, sadece tüm kod için "onbir çevirmek" kadranı uygulayabilirsiniz.

Bu optimizasyonların programınızın yürütme süresindeki etkili sonucu genellikle başka yerlerde çalışan kodlardan etkilenir. Bir dosyayı okuma, bir dbase sorgusu yürütme, vb. JIT optimizer'ın çalışması tamamen görünmez olur. Gerçi umursamıyor :)

JIT iyileştirici, çoğunlukla milyonlarca kez test edildiğinden oldukça güvenilir bir koddur. Programınızın Release derleme sürümünde sorun olması son derece nadirdir. Ancak olur. Hem x64 hem de x86 titremelerinin yapılarla ilgili sorunları vardı. X86 titreşimi, kayan nokta tutarlılığı ile ilgili sorun yaşar ve kayan nokta hesaplamasının ara maddeleri, bir FPU kaydında, belleğe akıtıldığında kesilmek yerine 80 bit hassasiyette tutulduğunda oldukça farklı sonuçlar üretir.


23
Tüm koleksiyonların dizi (ler) kullandığını sanmıyorum : LinkedList<T>çok sık kullanılmasa bile, yapmaz.
26'da svick

CLR'nin FPU'yu 53-bit hassasiyetle (64-bit geniş çiftler eşleştirerek) yapılandırdığını düşünüyorum, bu yüzden Float64 değerleri için 80 bit genişletilmiş çift hesaplamalar olmamalıdır. Ancak, Float32 hesaplamaları bu 53 bit hassasiyetle hesaplanabilir ve yalnızca belleğe kaydedildiğinde kesilebilir.
Valilik

2
volatileAnahtar kelime bir yığın çerçevede saklanan yerel değişkenler için geçerli değildir. Msdn.microsoft.com/en-us/library/x13ttww7.aspx adresindeki belgelerden : "Geçici anahtar kelime yalnızca bir sınıfın veya yapının alanlarına uygulanabilir. Yerel değişkenler geçici olarak bildirilemez."
Kris Vandermotten

8
alçakgönüllü bir değişiklik olarak, bu konuda gerçekten fark yaratan Debugve Releasebu konuda inşa eden şey, normalde açık olan Releaseancak kapalı olan "kodu optimize et" onay kutusudur Debug. Sadece okuyucuların Visual Studio'daki proje özellik sayfasında bulunanların ötesine geçen iki yapı yapılandırması arasında "sihirli", görünmez farklılıklar olduğunu düşünmeye başlamamasını sağlamaktır.
chiccodoro

3
Belki de System.Diagnostics.Debug'daki yöntemlerin neredeyse hiçbirinin hata ayıklama derlemesinde herhangi bir şey yapmadığını belirtmeye değer. Ayrıca değişkenler o kadar çabuk kesinleşmez bkz. ( Stackoverflow.com/a/7165380/20553 ).
Martin Brown

23
  1. Evet, birçok performans farkı vardır ve bunlar gerçekten kodunuzun her yerinde geçerlidir. Hata ayıklama çok az performans optimizasyonu ve serbest bırakma modu yapar;

  2. Yalnızca DEBUGsabite dayanan kod, bir sürüm derlemesiyle farklı performans gösterebilir. Bunun yanında herhangi bir sorun görmemelisiniz.

Bağlıdır çerçeve kod örneği DEBUGsabit olan Debug.Assert()özniteliği yöntem olup, [Conditional("DEBUG)"]tanımlandığı gibidir. Bu, aynı zamanda DEBUGsabite bağlı olduğu ve bunun serbest bırakma yapısına dahil olmadığı anlamına gelir .


2
Bunların hepsi doğru, ama bir farkı ölçebilir misiniz? Veya bir programı kullanırken bir fark fark ettiniz mi? Tabii ki hiç kimseyi yazılımlarını hata ayıklama modunda yayınlamaya teşvik etmek istemiyorum, ancak soru büyük bir performans farkı olup olmadığı ve bunu göremiyorum.
testalino

2
Ayrıca, hata ayıklama sürümlerinin orijinal kaynak koduyla yayın sürümlerinden çok daha yüksek bir korelasyona sahip olduğu da belirtilmelidir. Birinin yürütülebilir dosyalarınızı tersine mühendislik yapmaya çalışacağını (ancak olası olmadığını) düşünüyorsanız, hata ayıklama sürümlerini dağıtarak bunları kolaylaştırmak istemezsiniz.
jwheron

2
@testalino - Bugünlerde zor. İşlemciler, kullanıcının eylemi nedeniyle kodun gerçekten yürütülmesini bir işlemin beklemesini hızlandırdı, bu yüzden bu göreceli. Ancak, aslında uzun bir süreç yapıyorsanız, evet fark edeceksiniz. Aşağıdaki kod örn altında% 40 daha yavaş çalışır DEBUG: AppDomain.CurrentDomain.GetAssemblies().Sum(p => p.GetTypes().Sum(p1 => p1.GetProperties().Length)).
Pieter van Ginkel

2
Ayrıca, asp.netaçıksanız ve yayınlamak yerine hata ayıklama kullanıyorsanız, sayfanıza MicrosoftAjax.debug.jsyaklaşık 7 bin satırlık gibi bazı komut dosyaları eklenebilir .
BrunoLM

13

Bu büyük ölçüde uygulamanızın doğasına bağlıdır. Uygulamanız UI-ağırsa, modern bir bilgisayara bağlı en yavaş bileşen kullanıcı olduğu için muhtemelen herhangi bir fark görmeyeceksiniz. Bazı kullanıcı arayüzü animasyonları kullanıyorsanız, DEBUG derlemesinde çalışırken fark edilir bir gecikmeyi algılayıp algılayamayacağınızı test etmek isteyebilirsiniz.

Ancak, çok fazla hesaplama ağırlıklı hesaplamanız varsa, farkları fark edersiniz (hesapların doğasına bağlı olsa da, @Pieter'den% 40 kadar yüksek olabilir).

Temelde bir tasarım ödünleşimi. DEBUG derlemesi altında yayınlıyorsanız, kullanıcılar sorun yaşarsa, daha anlamlı bir geri izleme alabilir ve çok daha esnek bir teşhis yapabilirsiniz. DEBUG yapısında serbest bırakarak, optimize edici belirsiz Heisenbugs üreten kaçının .


11
  • Deneyimlerim, bir Release derlemesinde orta büyüklükteki veya daha büyük uygulamaların belirgin şekilde daha duyarlı olduğudur. Başvurunuzla bir deneyin ve nasıl hissettirdiğini görün.

  • Release derlemeleri ile sizi ısırabilecek bir şey, Debug derleme kodunun bazen yarış koşullarını ve diğer diş açmayla ilgili hataları baskılayabilmesidir. Optimize edilmiş kod, talimatların yeniden sıralanmasına neden olabilir ve daha hızlı yürütme, bazı yarış koşullarını daha da kötüleştirebilir.


9

Üretime bir .NET Hata Ayıklama derlemesi bırakmamalısınız. Edit-and-Continue özelliğini destekleyen veya başka neler bilen çirkin kodlar içerebilir. Bildiğim kadarıyla, bu sadece VB değil C # olur (not: orijinal yazı C # olarak etiketlenir) , ancak yine de Microsoft'un bir Hata Ayıklama derlemesi ile yapmasına izin verdiğini düşündüğü için duraklatmak için bir neden belirtmelidir. Aslında, .NET 4.0'dan önce, VB kodu, Düzenle ve Devam Et'i desteklemek için oluşturduğunuz olaylara sahip nesnelerin örnek sayısı ile orantılı olarak bellek sızdırıyor. (Bunun https://connect.microsoft.com/VisualStudio/feedback/details/481671/vb-classes-with-events-are-not-garbage-collected-when-debugging , oluşturulan kod uyarınca düzeltildiği bildirilse de kötü görünüyor, WeakReferencenesne oluşturuyor ve bunları statik bir listeye ekliyorkilit tutan ) Kesinlikle bir üretim ortamında hata ayıklama desteği bu tür herhangi istemiyoruz!


Debug derlemelerini birçok kez serbest bıraktım ve bir sorun görmedim. Belki de tek fark, sunucu tarafı uygulamamızın birçok kullanıcıyı destekleyen bir web uygulaması olmamasıdır. Ancak çok yüksek işlem yüküne sahip bir sunucu tarafı uygulamasıdır. Deneyimlerime göre Debug ve Release arasındaki fark tamamen teorik görünüyor. Uygulamalarımızdan hiçbirinde pratik bir fark görmedim.
Sam Goldberg

5

Benim tecrübelerime göre, Yayın modundan çıkan en kötü şey belirsiz "yayın hataları" dır. IL (ara dil) Yayınlama modunda optimize edildiğinden, Hata Ayıklama modunda ortaya çıkmayacak hatalar olasılığı vardır. Bu sorunu kapsayan başka SO soruları vardır: Yayın sürümünde hataların hata ayıklama modunda bulunmamasının yaygın nedenleri

Bu, basit bir konsol uygulamasının Hata Ayıklama modunda mükemmel şekilde iyi çalışacağı bir veya iki kez başıma geldi, ancak tam olarak aynı giriş verildiğinde, Yayın modunda hata verecekti. Bu hataların ayıklanması son derece zordur (Yayın modunun tanımı gereği ironik olarak).


Takip etmek için, bir Sürüm Hatası örneği veren bir makale: codeproject.com/KB/trace/ReleaseBug.aspx
Roly

Uygulama hata ayıklansa bile hata ayıklama ayarlarıyla sınanıp onaylanırsa, bu durum dağıtım sırasında dağıtım derlemesinin başarısız olmasına neden oluyorsa yine de bir sorundur.
Øyvind Bråthen

4

1) büyük ölçüde uygulamanıza bağlı olduğunu söyleyebilirim. Genellikle, fark o kadar da büyük değildir. Çok fazla ölçüm yaptım ve çoğu zaman bir fark göremedim. Yönetilmeyen kod, çok sayıda büyük diziler ve bunun gibi şeyler kullanırsanız, performans farkı biraz daha büyüktür, ancak farklı bir dünya değildir (C ++ gibi). 2) Genellikle sürüm kodunda daha az hata gösterilir (daha yüksek tolerans), bu nedenle bir anahtarın iyi çalışması gerekir.


1
GÇ bağlı kod için, bir sürüm derlemesi bu hata ayıklama daha kolay olamazdı.
Richard

0
    **Debug Mode:**
    Developer use debug mode for debugging the web application on live/local server. Debug mode allow developers to break the execution of program using interrupt 3 and step through the code. Debug mode has below features:
   1) Less optimized code
   2) Some additional instructions are added to enable the developer to set a breakpoint on every source code line.
   3) More memory is used by the source code at runtime.
   4) Scripts & images downloaded by webresource.axd are not cached.
   5) It has big size, and runs slower.

    **Release Mode:**
    Developer use release mode for final deployment of source code on live server. Release mode dlls contain optimized code and it is for customers. Release mode has below features:
   1) More optimized code
   2) Some additional instructions are removed and developer cant set a breakpoint on every source code line.
   3) Less memory is used by the source code at runtime.
   4) Scripts & images downloaded by webresource.axd are cached.
   5) It has small size, and runs fast.

2
sürüm modundayken bazen bir listenin ilk öğeleri doğru şekilde numaralandırılmamıştır. Ayrıca listedeki bazı öğeler çoğaltılır. :)
Gian Paolo
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.