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
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.