Switch ifadeleri, derleyici optimizasyonları nedeniyle genellikle eşdeğer if-else-if ifadelerinden (örneğin bu makalede açıklanan ) daha hızlıdır .
Bu optimizasyon aslında nasıl çalışıyor? İyi bir açıklaması olan var mı?
Switch ifadeleri, derleyici optimizasyonları nedeniyle genellikle eşdeğer if-else-if ifadelerinden (örneğin bu makalede açıklanan ) daha hızlıdır .
Bu optimizasyon aslında nasıl çalışıyor? İyi bir açıklaması olan var mı?
Yanıtlar:
Derleyici, uygun olan yerlerde atlama tabloları oluşturabilir. Örneğin, üretilen koda bakmak için yansıtıcıyı kullandığınızda, dizelerdeki devasa anahtarlar için derleyicinin bunları göndermek için bir karma tablo kullanan bir kod üreteceğini göreceksiniz. Karma tablo, dizeleri anahtar olarak ve case
kodlara değer olarak delegeler kullanır .
Bu, çok sayıda zincirleme if
testten daha asimptotik daha iyi çalışma süresine sahiptir ve aslında nispeten az sayıda dizge için bile daha hızlıdır.
Bu, tipik olarak if..else if ..
bir kişi tarafından önemsiz bir şekilde switch ifadesine dönüştürülebilen bir diziyle karşılaşan herhangi bir modern derleyici gibi hafif bir basitleştirmedir , derleyici de yapacaktır. Ancak daha fazla eğlence eklemek için derleyici sözdizimi ile kısıtlanmamıştır, bu nedenle dahili olarak aralıkların, tek hedeflerin vb. Karışımına sahip "anahtar" benzeri ifadeler üretebilir - ve bunu hem switch hem de if için yapabilirler (ve yaparlar). .else ifadeleri.
Her neyse, Konrad'ın cevabının bir uzantısı, derleyicinin bir atlama tablosu oluşturabileceğidir, ancak bu mutlaka garanti edilmez (veya istenmez). Çeşitli nedenlerden dolayı atlama tabloları, modern işlemcilerdeki şube tahmin edicilerine kötü şeyler yapar ve tablolar davranışları önbelleğe almak için kötü şeyler yapar, örn.
switch(a) { case 0: ...; break; case 1: ...; break; }
Bir derleyici gerçekten bunun için bir atlama tablosu oluşturduysa if..else if..
, atlama tablosunun dallanma tahminini bozması nedeniyle alternatif stil kodunun daha yavaş olması muhtemeldir .
Maç yok istatistikleri iyi olmayabilir.
Kaynağı gerçekten indirirseniz, hem if hem de anahtar durumunda 21 eşleşme yok değerleri olarak bilinir. Bir derleyici, hangi ifadenin her zaman çalıştırılması gerektiğini bilerek soyutlama yapabilmelidir ve bir CPU, tahmini doğru şekilde dallara ayırabilmelidir.
Daha ilginç olan durum, bence her vakanın bozulmamasıdır, ancak deneyin kapsamı bu olmayabilir.
Switch / case deyimleri genellikle daha hızlı 1 düzey derinlikte olabilir, ancak 2 veya daha fazlasına girmeye başladığınızda, switch / case deyimleri, iç içe geçen if / else deyimlerinin 2-3 katını almaya başlar.
Bu makale, bu tür ifadeler iç içe geçtiğinde hız farklılıklarını vurgulayan bazı hız karşılaştırmalarına sahiptir .
Örneğin, testlerine göre aşağıdaki gibi örnek kod:
if (x % 3 == 0)
if (y % 3 == 0)
total += 3;
else if (y % 3 == 1)
total += 2;
else if (y % 3 == 2)
total += 1;
else
total += 0;
else if (x % 3 == 1)
if (y % 3 == 0)
total += 3;
else if (y % 3 == 1)
total += 2;
else if (y % 3 == 2)
total += 1;
else
total += 0;
else if (x % 3 == 2)
if (y % 3 == 0)
total += 3;
else if (y % 3 == 1)
total += 2;
else if (y % 3 == 2)
total += 1;
else
total += 0;
else
if (y % 3 == 0)
total += 3;
else if (y % 3 == 1)
total += 2;
else if (y % 3 == 2)
total += 1;
else
total += 0;
eşdeğer switch / case ifadesinin çalışması için geçen sürenin yarısında bitti :
switch (x % 3)
{
case 0:
switch (y % 3)
{
case 0: total += 3;
break;
case 1: total += 2;
break;
case 2: total += 1;
break;
default: total += 0;
break;
}
break;
case 1:
switch (y % 3)
{
case 0: total += 3;
break;
case 1: total += 2;
break;
case 2: total += 1;
break;
default: total += 0;
break;
}
break;
case 2:
switch (y % 3)
{
case 0: total += 3;
break;
case 1: total += 2;
break;
case 2: total += 1;
break;
default: total += 0;
break;
}
break;
default:
switch (y % 3)
{
case 0: total += 3;
break;
case 1: total += 2;
break;
case 2: total += 1;
break;
default: total += 0;
break;
}
break;
}
Evet, ilkel bir örnek, ama asıl noktayı gösteriyor.
Dolayısıyla, yalnızca bir düzey derinliğinde olan basit türler için anahtar / durum kullanımı olabilir, ancak daha karmaşık karşılaştırmalar ve birden çok iç içe geçmiş düzey için klasik if / else yapılarını kullanın.