SORU
18 EYLÜL 2008, PERŞEMBE


Türü, dize ya da ' if ' daha hızlı geçiş nedir?

Dize karşılaştırma olarak almak için bir kod yolu belirleme veya başka tür iffing seçeneği var diyelim:

Hangisi daha hızlı ve neden?

switch(childNode.Name)
{
    case "Bob":
      break;
    case "Jill":
      break;
    case "Marko":
      break;
}

if(childNode is Bob)
{
}
elseif(childNode is Jill)
{
}
else if(childNode is Marko)
{
}

Güncelleme:Bunu sormamın asıl nedeni switch deyimi bir durum olarak sayar ne perculiar olmasıdır. Örneğin alışkanlık değişkenleri, sadece ana Meclisine taşındı hangi sabitleri kullanmak için izin verir. Bu kısıtlama yapıyor bazı funky şeyler yüzünden sanmıştım. Eğer elseifs bir poster olarak yorumladı () için neden dava tablolarda değişkenler İzin Verilmiyor o zaman? çeviri ise sadece

Uyarı:Post-optimize ediyorum. Bu yöntemi denirbirçokapp yavaş bir bölümünde kere.

CEVAP
24 EYLÜL 2008, ÇARŞAMBA


Greg profilini sonuçları için harika kesin senaryo ortaya çıkardı, ama ilginçtir, göreceli maliyetleri farklı yöntem değişikliği önemli ölçüde gözardı sayıda değişik faktörler de dahil olmak üzere sayı türleri karşılaştırılan ve göreli frekans ve herhangi bir desen temel veri.

Cevabı basit, o kimse-ebilmek söylemek sen ne kadar performans farkı olacak senin belirli bir senaryo gerekir ölçmek için performans farklı şekillerde kendini kendi sistemi için bir doğru cevap.

/Eğer Başka bir zincir tip karşılaştırmaları küçük bir sayı için etkili bir yaklaşım olduğunu, ya da eğer güvenilir bir şekilde tahmin ederseniz birkaç tür gördüklerin çoğunluğunu oluşturur. Bu yaklaşım, potansiyel bir sorun türlerinin sayısı arttıkça, idam olması gereken karşılaştırma sayısı da artar. ben şu çalıştırmak için:

int value = 25124;
if(value == 0) ...
else if (value == 1) ...
else if (value == 2) ...
...
else if (value == 25124) ... 

koşulları ise önceki her doğru blok girilmeden önce değerlendirilmesi gerekir. Diğer taraftan

switch(value) {
 case 0:...break;
 case 1:...break;
 case 2:...break;
 ...
 case 25124:...break;
}

kodu doğru bit için basit bir sıçrama yapacak.

Sizin örnekte daha karmaşık bir hal alır nerede diğer yöntem dizeleri bir geçiş yapmak yerine biraz daha karmaşık bir hal alır tamsayı kullanır. Düşük düzeyde, dizeleri tamsayı değerleri aynı şekilde C yakılabilir mi# derleyicisi bu sizin için çalışmasını sağlamak için bazı büyü yapar.

Eğer switch deyimi "derleyici otomatik olarak en iyi olduğunu düşündüğü şeyi yapıyor) geçiş dizeleri/başka bir aynı zincir bir kod oluşturur." yeterince küçükse

switch(someString) {
 case "Foo": DoFoo(); break;
 case "Bar": DoBar(); break;
 default: DoOther; break;
}
is the same as:
if(someString == "Foo") {
 DoFoo();
}
else if(someString == "Bar") {
 DoBar();
}
else {
 DoOther();
}

Bir zamanlar listenin öğeleri sözlüğü alır "yeterince büyük" derleyici otomatik olarak oluşturmak için dahili bir sözlük bu haritalardan dizeler geçiş yapmak için bir tamsayı dizin ve sonra bir geçiş göre dizin.

Bu (Sadece tip için rahatsız edeceğim daha fazla girdi hayal gibi bir şey görünüyor

Statik bir alan"," sınıf tipi Sözlük<string, int> ve karıştırılmış adı verilen deyim . anahtarı içeren ile ilişkili konum gizli olarak tanımlanır

//Make sure the dictionary is loaded
if(theDictionary == null) { 
 //This is simplified for clarity, the actual implementation is more complex 
 // in order to ensure thread safety
 theDictionary = new Dictionary<string,int>();
 theDictionary["Foo"] = 0;
 theDictionary["Bar"] = 1;
}
int switchIndex;
if(theDictionary.TryGetValue(someString, out switchIndex)) {
 switch(switchIndex) {
  case 0: DoFoo(); break;
  case 1: DoBar(); break;
 }
}
else {
 DoOther();
}

Kaçtım o bazı hızlı testler, Eğer/Else yöntemi 3x hızlı olarak 3 farklı tip için anahtar türlerini rastgele dağıtılır) gibi. 25 tür geçiş anahtarı iki kat daha hızlı 50 tür küçük bir farkla (yüzde 16) göre daha hızlıdır.

Eğer türlerinin çok sayıda geçiş olacak, 3. bir yöntem öneriyorum:

 private delegate void NodeHandler(ChildNode node);

 static Dictionary<RuntimeTypeHandle, NodeHandler> TypeHandleSwitcher =
      CreateSwitcher();
 private static Dictionary<RuntimeTypeHandle, NodeHandler> CreateSwitcher() {
  Dictionary<RuntimeTypeHandle, NodeHandler> ret = 
    new Dictionary<RuntimeTypeHandle, NodeHandler>();

  ret[typeof(Bob).TypeHandle] = HandleBob;
  ret[typeof(Jill).TypeHandle] = HandleJill;
  ret[typeof(Marko).TypeHandle] = HandleMarko;
  return ret;
 }

 void HandleChildNode(ChildNode node) {
  NodeHandler handler;
  if(TaskHandleSwitcher.TryGetValue(Type.GetRuntimeType(node), out handler)) {
   handler(node);
  }
  else {
   //Unexpected type...
  }
 }
}

Bu Ted Elliot önerdi ne benzer, ancak çalışma zamanı tür işler yerine tam tür nesnelerin kullanımı, yansıma yoluyla type nesne yükleme yükünü önler.

İşte benim makine biraz hızlı zamanlama:

Testing 3 iterations with 5,000,000 data elements (mode=Random) and 5 types
Method                Time    % of optimal
If/Else               179.67  100.00
TypeHandleDictionary  321.33  178.85
TypeDictionary        377.67  210.20
Switch                492.67  274.21

Testing 3 iterations with 5,000,000 data elements (mode=Random) and 10 types
Method                Time    % of optimal
If/Else               271.33  100.00
TypeHandleDictionary  312.00  114.99
TypeDictionary        374.33  137.96
Switch                490.33  180.71

Testing 3 iterations with 5,000,000 data elements (mode=Random) and 15 types
Method                Time    % of optimal
TypeHandleDictionary  312.00  100.00
If/Else               369.00  118.27
TypeDictionary        371.67  119.12
Switch                491.67  157.59

Testing 3 iterations with 5,000,000 data elements (mode=Random) and 20 types
Method                Time    % of optimal
TypeHandleDictionary  335.33  100.00
TypeDictionary        373.00  111.23
If/Else               462.67  137.97
Switch                490.33  146.22

Testing 3 iterations with 5,000,000 data elements (mode=Random) and 25 types
Method                Time    % of optimal
TypeHandleDictionary  319.33  100.00
TypeDictionary        371.00  116.18
Switch                483.00  151.25
If/Else               562.00  175.99

Testing 3 iterations with 5,000,000 data elements (mode=Random) and 50 types
Method                Time      % of optimal
TypeHandleDictionary  319.67    100.00
TypeDictionary        376.67    117.83
Switch                453.33    141.81
If/Else               1,032.67  323.04

Benim makinede en azından yazın kolu sözlük yaklaşımı dağılımı 15 farklı tür bir şey için diğer hepsini yener bu tür girdi olarak kullanılan yöntem, rastgele.

Diğer taraftan, giriş tamamen ilk yöntem ise/başka zincirinde kontrol türü oluşurçokdaha hızlı:

Testing 3 iterations with 5,000,000 data elements (mode=UniformFirst) and 50 types
Method                Time    % of optimal
If/Else               39.00   100.00
TypeHandleDictionary  317.33  813.68
TypeDictionary        396.00  1,015.38
Switch                403.00  1,033.33

Eğer giriş her zaman/başka zincirindeki son şey ise, tam tersine, tamamen ters etki yaptı:

Testing 3 iterations with 5,000,000 data elements (mode=UniformLast) and 50 types
Method                Time      % of optimal
TypeHandleDictionary  317.67    100.00
Switch                354.33    111.54
TypeDictionary        377.67    118.89
If/Else               1,907.67  600.52

Eğer sen-ebilmek yapmak bazı varsayımlar hakkında fikrini alabilir en iyi performans bir melez yaklaşım nerede yapıyorsanız/başka çekler için birkaç türleri vardır, en yaygın, ve sonra geri düşmek için bir sözlük odaklı yaklaşımı ise, bu başarısız.

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

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • jonathepianist

    jonathepiani

    31 Temmuz 2008
  • Learn Math Tutorials

    Learn Math T

    20 Kasım 2011
  • Microsoft Research

    Microsoft Re

    24 EKİM 2008

İLGİLİ SORU / CEVAPLAR