Statik yöntemlerin performansı ve örnek yöntemlerinin performansı


108

Sorum, statik yöntemlerin performans özelliklerine karşı örnek yöntemlerle ve ölçeklenebilirlikleriyle ilgilidir. Bu senaryo için tüm sınıf tanımlarının tek bir derlemede olduğunu ve birden çok ayrı işaretçi türünün gerekli olduğunu varsayın.

Düşünmek:

public sealed class InstanceClass
{
      public int DoOperation1(string input)
      {
          // Some operation.
      }

      public int DoOperation2(string input)
      {
          // Some operation.
      }

      // … more instance methods.
}

public static class StaticClass
{
      public static int DoOperation1(string input)
      {
          // Some operation.
      }

      public static int DoOperation2(string input)
      {
          // Some operation.
      }

      // … more static methods.
}

Yukarıdaki sınıflar bir yardımcı stil modelini temsil eder.

Bir örnek sınıfında, örnek yönteminin çözümlenmesi, StaticClass'ın aksine yapmak için biraz zaman alır.

Sorularım:

  1. Durumun korunması bir sorun olmadığında (alan veya özellik gerekli değildir), statik bir sınıf kullanmak her zaman daha mı iyidir?

  2. Önemli sayıda bu statik sınıf tanımlarının olduğu yerlerde (örneğin, her biri birkaç statik yöntemle 100), bu durum, aynı sayıda örnek sınıfı tanımına kıyasla yürütme performansını veya bellek tüketimini olumsuz etkileyecek mi?

  3. Aynı örnek sınıfı içinde başka bir yöntem çağrıldığında, örnek çözümlemesi hala devam ediyor mu? Örneğin, [this] anahtar kelimesini aynı örneğin this.DoOperation2("abc")içinden kullanmak gibi DoOperation1.



"örnek çözünürlüğü" ile neyi kastediyorsunuz? IL düzeyinde, "bu" işaretçi, diğer herhangi bir yerel değişken gibi kullanılabilir. Aslında, bazı eski CLR / JIT sürümlerinde, 'bu' işaretine dokunmaması koşuluyla bir NULL üzerinde bir örnek yöntemi çağırabilirsiniz - kod az önce geçti ve hiçbir şey üzerinde çöktü .. şimdi CLR / JIT açık null içeriyor her üyenin çağırdığını kontrol et ..
quetzalcoatl

> vijaymukhi.com/documents/books/ilbook/chap8.htm ve 'çağrı örneği' yerine sadece 'ara'. İlki 'bu' parametresini bekler ve ikincisi - yapmaz.
quetzalcoatl

@Quetzalcoatl karışıklık için özür dilerim, soru aynı örnekten yönteme daha çok yöntemdi ve bu örneğin kendi kendine çözülmesini gerektiriyorsa.
Bernie White

1
@quetzalcoatl " thisBir sınıf kendi başına bir örnek yöntemi çağırdığında derleyici bir şeye işaret eden bir şeyi kontrol etmekten kurtulur mu?"
Jon Hanna

Yanıtlar:


152

Teoride, statik bir yöntem örnek yöntemden biraz daha iyi performans göstermelidir, diğer tüm şeyler, ekstra gizli thisparametre nedeniyle eşittir .

Pratikte, bu o kadar az fark yaratır ki, çeşitli derleyici kararlarının gürültüsünde gizlenir. (Bu nedenle, iki kişi, birbiriyle çelişen sonuçlarla birini diğerinden daha iyi "kanıtlayabilir"). En azından this, normalde bir kayıt defterinde geçirildiği ve genellikle başlangıçta bu kayıtta olduğu için.

Bu son nokta, teoride, bir nesneyi parametre olarak alan ve onunla bir şeyler yapan statik bir yöntemin, aynı nesnedeki eşdeğerden biraz daha az iyi olmasını beklememiz gerektiği anlamına gelir. Yine de, fark o kadar küçüktür ki, ölçmeye çalışırsanız, muhtemelen başka bir derleyici kararını ölçmek zorunda kalırsınız. (Özellikle bu referansın tüm zaman boyunca bir kayıtta olma olasılığı da oldukça yüksek olduğu için).

Gerçek performans farklılıkları, bellekte doğal olarak statik olması gereken bir şeyi yapmak için nesnelerin yapay olarak bulunup bulunmadığına ya da doğal olarak örnek olması gereken şeyi yapmak için karmaşık yollarla nesne geçiş zincirlerini birbirine karıştırmanıza bağlı olacaktır.

Dolayısıyla 1 numara için. Durumu korumak bir sorun değilse, statik olmak her zaman daha iyidir, çünkü statik bunun içindir . Derleyici optimizasyonları ile güzelce oynamanın genel bir kuralı olsa da, bu bir performans sorunu değil - birinin normal kullanımla ortaya çıkan durumları optimize etme çabasına, garip kullanımla gelenlerden daha fazla gitmesi muhtemeldir.

Sayı 2. Fark etmez. Her üye için sınıf başına belirli bir miktar maliyet vardır, bu hem ne kadar meta veri olduğu, gerçek DLL veya EXE dosyasında ne kadar kod olduğu ve ne kadar jitted kod olacağı ile ilgilidir. Bu, ister örnek ister statik olsun aynıdır.

3. maddede thisolduğu gibi this. Ancak şunu unutmayın:

  1. thisParametre, belirli bir kayıt geçirilir. Aynı sınıf içinde bir örnek yöntemi çağırırken, muhtemelen o kayıtta olacaktır (saklanmadıkça ve herhangi bir nedenle kayıt kullanılmadıysa) ve bu nedenle, ayarlanması thisgereken şeye ayarlamak için herhangi bir eylem gerekmez . . Bu, bir dereceye kadar, örneğin yöntemin ilk iki parametresinin yaptığı bir çağrının ilk iki parametresi olması için geçerlidir.

  2. thisBoş olmadığı açık olacağından , bu bazı durumlarda çağrıları optimize etmek için kullanılabilir.

  3. thisBoş olmadığı açık olacağından , bu satır içi yöntem çağrılarını tekrar daha verimli hale getirebilir, çünkü yöntem çağrısını taklit etmek için üretilen kod, yine de ihtiyaç duyabileceği bazı boş kontrolleri atlayabilir.

  4. Bununla birlikte, boş çekler ucuzdur!

Örnek yöntemlerden ziyade bir nesneye etki eden genel statik yöntemlerin, http://joeduffyblog.com/2011/10/23/on-generics-and-some-of- adresinde tartışılan bazı maliyetleri azaltabileceğini belirtmek gerekir. the-ilişkili-genel giderler / belirli bir tür için belirtilen statik çağrılmadığı durumda. Kendisinin de belirttiği gibi, "Bir kenara, uzatma yöntemlerinin genel soyutlamaları daha fazla oyun için ödeme yapmanın harika bir yolu olduğu ortaya çıktı."

Ancak, bunun yalnızca yöntem tarafından kullanılan, başka türlü var olmayan diğer türlerin somutlaştırılmasıyla ilgili olduğuna dikkat edin. Bu nedenle, pek çok durum için gerçekten geçerli değildir (bu türü kullanan başka bir örnek yöntemi, başka bir yerde bu türü kullanan başka bir kod).

Özet:

  1. Çoğunlukla örnek ve statik arasındaki performans maliyetleri ihmal edilebilir seviyenin altındadır.
  2. Örneğin, statikliği kötüye kullandığınızda veya tam tersi durumda, genellikle ne tür maliyetler olur. Statik ve örnek arasındaki kararınızın bir parçası yapmazsanız, doğru sonucu alma olasılığınız daha yüksektir.
  3. Başka bir türdeki statik genel yöntemlerin, örnek jenerik yöntemlere göre daha az türün oluşturulmasına yol açtığı nadir durumlar vardır, bu da bazen nadiren kullanılmasını sağlamak için küçük bir fayda sağlayabilir (ve "nadiren", başvurunun ömrü, ne sıklıkta çağrıldığı değil). O makalede bahsettiği şeyi anladıktan sonra, bunun zaten çoğu statik vs örnek kararıyla% 100 alakasız olduğunu göreceksiniz. Düzenleme: Ve çoğunlukla ngen ile bu maliyete sahiptir, jitted kod ile değil.

Düzenleme: Boş kontrollerin ne kadar ucuz olduğuna dair bir not (yukarıda iddia ettiğim). .NET'teki çoğu boş denetim, boş değeri kontrol etmez, bunun yerine çalışacağı varsayımıyla yapacaklarına devam eder ve bir erişim istisnası olursa, bir NullReferenceException. Bu nedenle, çoğunlukla C # kodu kavramsal olarak bir örnek üyesine eriştiği için boş bir kontrol içerdiğinde, başarılı olursa maliyeti aslında sıfırdır. Bazı satır içi çağrılar bir istisna olabilir (çünkü bir örnek üyesi çağırmış gibi davranmak isterler) ve aynı davranışı tetiklemek için bir alana vururlar, bu nedenle de çok ucuzdurlar ve yine de çoğu zaman dışarıda bırakılabilirler. (örneğin, yöntemdeki ilk adım bir alana olduğu gibi erişmeyi içeriyorsa).


Statik ve örnek sorununun önbellek tutarlılığı üzerinde herhangi bir etkisi olup olmadığı hakkında yorum yapabilir misiniz? Birine veya diğerine güvenmenin önbellekte eksikliklere neden olma olasılığı daha mı yüksek? Nedenini açıklayan iyi bir taslak var mı?
scriptocalypse

@scriptocalypse Pek değil. Talimat önbelleği herhangi bir fark görmez ve bu seviyede verilere thisaçık bir parametre yoluyla veya bu parametre aracılığıyla erişim arasında çok fazla fark yoktur . Buradaki daha büyük etki, verilerin ilgili verilere ne kadar yakın olduğu (değer türü alanları veya dizi değerleri, referans türü alanlarındaki verilerden daha yakındır) ve erişim kalıpları olacaktır.
Jon Hanna

"Teoride, bir nesneyi parametre olarak alan ve onunla bir şeyler yapan statik bir yöntemin, aynı nesnedeki bir örnek olarak eşdeğerinden biraz daha az iyi olmasını beklemeliyiz." - Yukarıdaki örnek yöntemi alırsa mı demek istiyorsunuz? parametre dize yerine nesne olarak, statik olmayan daha mı iyi? Örneğin: Statik yöntemimin nesneyi parametre olarak alması ve dizgeye dizgeleştirmesi ve dizge döndürmesi var. bu durumda statik olmayan kullanmayı mı öneriyorsunuz?
batmaci

1
@batmaci Demek istediğim obj.DoSomehting(2), bundan biraz daha ucuz olma ihtimali çok yüksek, DoSomething(obj, 2)ama aynı zamanda da söylediğim gibi, fark o kadar küçük ve son derlemede farklı olabilecek küçük şeylere o kadar bağlı ki, gerçekten endişelenmeye değmez. Bir şeyi bir dizgeye serileştirmek kadar pahalı (burada oyundaki farklılıkların türüne göre) bir şey yapıyorsanız, o zaman özellikle anlamsızdır.
Jon Hanna

Bu mükemmel yanıtta belki de bariz ama önemli olan bir şey eksik: bir örnek yöntemi bir örnek gerektirir ve bir örnek oluşturmak ucuz değildir. Varsayılan bile olsa ctortüm alanların başlatılması gerekir. Zaten bir örneğiniz olduğunda, bu cevap geçerlidir ("diğer tüm şeyler eşittir"). Tabii ki, pahalı bir cctorstatik yöntemleri de yavaşlatabilir, ancak bu yalnızca ilk çağrıda örnek yöntemlerine eşit şekilde uygulanır. Ayrıca bkz. Docs.microsoft.com/en-us/previous-versions/dotnet/articles/…
Abel

8

Durumun korunması bir sorun olmadığında (alan veya özellik gerekli değildir), statik bir sınıf kullanmak her zaman daha mı iyidir?

Evet derim. Bir şeyi staticbeyan ederken , vatansız infaz niyetini beyan edersiniz (bu zorunlu değildir, ancak kişinin bekleyeceği bir şeyin niyeti)

Bu statik sınıfların hatırı sayılır sayıda olduğu yerde (örneğin, her biri bir dizi statik yöntemle 100 diyelim), bu, aynı sayıda örnek sınıfıyla karşılaştırıldığında yürütme performansını veya bellek tüketimini olumsuz etkileyecek mi?

Statik sınıfların gerçekten durgun olduğundan emin değilseniz öyle düşünmeyin, çünkü kolay değilse bellek ayırmalarını bozun ve bellek sızıntıları yaşayın.

Aynı örnek sınıfı içinde başka bir yöntemi çağırmak için [this] anahtar sözcüğü kullanıldığında, örnek çözümlemesi hala devam ediyor mu?

Emin değilim, bu nokta hakkında (bu, CLR'nin tamamen uygulama ayrıntısıdır), ama evet düşünün.


Statik yöntemler alay edilemez, TDD yaparsanız veya sadece birim testi yaparsanız, bu testlerinize çok zarar verir.
trampster

@trampster Neden? Bu sadece bir mantık parçası. Verdiğinle kolayca dalga geçebilir misin? Doğru davranmak için. Ve statik yöntemlerin çoğu zaten bir işlevdeki özel mantık parçaları olacaktır.
M.Mimpen

@ M.Mimpen, küçük özel parçalara bıraktığınız sürece cezanız, herkese açık bir yöntemse ve onu diğer kapanışlarda kullanıyorsanız ve testinizde ne yaptığını değiştirmeniz gerekiyorsa, daha sonra takılıp kaldınız, dosya G / Ç veya veritabanı erişimi gibi şeyler veya ağ çağrıları vb., statik yönteme bir parametre olarak alay edilebilir bir bağımlılık enjekte etmediğinizi söylemediğiniz sürece, statik yönteme yerleştirilirse kilitlenemez hale gelecektir.
trampster,

-2

statik yöntemler daha hızlı ancak daha az OOP, eğer tasarım modellerini kullanacaksanız, statik yöntem muhtemelen kötü kod, iş mantığını statik olmadan daha iyi yazmak için, dosya okuma, WebRequest vb. gibi yaygın işlevler statik olarak daha iyi anlaşılır ... sorularınız evrensel değildir Cevap


16
İddialarınıza hiçbir argüman vermediniz.
ymajoros

2
@ fjch1997 2 oy veren kişi başka türlü düşünüyor (değeri ne olursa olsun). Olumsuz oyları yorumlamak stackexchange üzerinde pratik yapmak için teşvik edilir: meta.stackexchange.com/questions/135/…
ymajoros
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.