SORU
17 EKİM 2009, CUMARTESİ


Performans "" ve null türleri ile sürpriz

Sadece C Bölüm 4'e revize ediyorum# null türleri ele alan Derinliği ve kullanımı hakkında bir bölüm ekliyorum "gibi" yazmak için izin veren operatör,:

object o = ...;
int? x = o as int?;
if (x.HasValue)
{
    ... // Use x.Value in here
}

Bence bu çok güzel, ve o olabilir geliştirmek performans üzerinde C# 1 eşdeğer, kullanma"," ardından dökme sonra, bu şekilde biz sadece sormak için dinamik tip kontrolü bir kez, ve sonra basit bir değeri kontrol edin.

Bu böyle olmadığı, ancak görünüyor. Temel olarak bir nesne dizisinin içinde tüm tamsayılar denk aşağıda örnek bir test uygulaması dahil ettik - ama dizi null referanslar ve dize yönlendirmeler kutulu tamsayılar bir sürü içerir. Kriter önlemler kullanmanız gerek kod C# 1, kod "SERİ bir çözüm sadece eğlence için." operatör gibi kullanarak Benim şaşkınlık, C# 1 kod 20 kat daha hızlı bu durumda bile SERİ kodu (hangi ederdim beklenen yavaş, verilen kullanımına dahil) yener "gibi" kodu.

.Null türleri için isinst NET uygulama çok yavaş? Soruna neden olan unbox.any ek mi? Bunun başka bir açıklaması var mı? Şu anda performans hassas durumlarda, bu kullanmaya karşı bir uyarı eklemek zorunda kalacağım gibi geliyor...

Sonuçlar:

Oyuncular: 10000000 : 121< / ^ br . Olarak: 10000000 : 2211< / ^ br . SERİ: 10000000 : 2143

Kod:

using System;
using System.Diagnostics;
using System.Linq;

class Test
{
    const int Size = 30000000;

    static void Main()
    {
        object[] values = new object[Size];
        for (int i = 0; i < Size - 2; i  = 3)
        {
            values[i] = null;
            values[i 1] = "";
            values[i 2] = 1;
        }

        FindSumWithCast(values);
        FindSumWithAs(values);
        FindSumWithLinq(values);
    }

    static void FindSumWithCast(object[] values)
    {
        Stopwatch sw = Stopwatch.StartNew();
        int sum = 0;
        foreach (object o in values)
        {
            if (o is int)
            {
                int x = (int) o;
                sum  = x;
            }
        }
        sw.Stop();
        Console.WriteLine("Cast: {0} : {1}", sum, 
                          (long) sw.ElapsedMilliseconds);
    }

    static void FindSumWithAs(object[] values)
    {
        Stopwatch sw = Stopwatch.StartNew();
        int sum = 0;
        foreach (object o in values)
        {
            int? x = o as int?;
            if (x.HasValue)
            {
                sum  = x.Value;
            }
        }
        sw.Stop();
        Console.WriteLine("As: {0} : {1}", sum, 
                          (long) sw.ElapsedMilliseconds);
    }

    static void FindSumWithLinq(object[] values)
    {
        Stopwatch sw = Stopwatch.StartNew();
        int sum = values.OfType<int>().Sum();
        sw.Stop();
        Console.WriteLine("LINQ: {0} : {1}", sum, 
                          (long) sw.ElapsedMilliseconds);
    }
}

CEVAP
19 HAZİRAN 2010, CUMARTESİ


Açıkça JİT derleyici ilk dava için oluşturabilir makine kodu çok daha verimli olur. Gerçekten orada yardımcı olan bir kural bir nesne sadece kutulu değeri olarak aynı türü bir değişken için Kutusuz olmasıdır. Bu JİT derleyici çok verimli kod, dönüşümleri dikkate alınmalıdır değer oluşturmasına olanak sağlar.

operatör test kolay, sadece nesne null değil ve beklenen türde olup olmadığını kontrol edin, alır ama birkaç makine kodu talimat. Oyuncular da kolaydır, JİT derleyici nesne değeri bitlerin yerlerini bilen ve bunları doğrudan kullanır. Kopyalama veya dönüştürme gerçekleşir, makine kodu satır içi ama yaklaşık bir düzine talimatları alır. Bu geri içinde gerçekten verimli olması için gerekli .NET boks yaygın iken 1.0.

İnt için döküm? çok daha fazla çalışma gerektirir. Kutulu tamsayı değeri gösterimi Nullable<int> bellek düzeni ile uyumlu değil. Bir dönüşüm gerekli. şifre de mümkün kutulu numaralama türleri nedeniyle zordur. JİT derleyici CLR yardımcı fonksiyon işi JİT_Unbox_Nullable adlı bir çağrı oluşturur. Bu herhangi bir değer, çok fazla kod türlerini kontrol etmek için orada bir türü için genel amaçlı bir fonksiyondur. Ve değeri kopyalanır. Bu kodu mscorwks.dll ama makine kodu talimat yüzlerce içeriden kilitli olduğu için maliyetini tahmin etmek zordur muhtemelen.

Seri, OfType() uzatma yöntemi de kullanıroperatör ve döküm. Bu ancak genel bir türü için bir atama. JİT derleyici bir yardımcı işlev çağrısı oluşturur, JİT_Unbox() rasgele bir değer türü için bir döküm gerçekleştirebilirsiniz. 7 ** daha az çalışman gerekli olması için verilen cast olduğunca yavaş neden büyük bir açıklamam yok. Ngen.exe burada sorun neden olabilir şüpheli.

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

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Howard Pinsky

    Howard Pinsk

    6 AĞUSTOS 2006
  • Lupe Fiasco

    Lupe Fiasco

    23 ŞUBAT 2006
  • oHeymarvin

    oHeymarvin

    11 Temmuz 2013