SORU
27 Kasım 2014, PERŞEMBE


Performans: türü genel türetilmiştir

Oldukça anlayamadığım bir performans sorunu ile karşılaştım. Nasıl düzeltileceğini biliyorum ama Neden öyle anlamıyorum. Sadece eğlence için!
Konuşalım kodu. Kod sorunu yeniden oluşturmak için elimden geldiği kadar basit.
Genel bir sınıf diyebiliriz. Boş bir liste içinde ve yapıcı T bir şey yok. Listede IEnumerable<T> bir yöntem, örneğin Any() çağıran Run yöntem vardır.

public class BaseClass<T>
{
    private List<T> _list = new List<T>();

    public BaseClass()
    {
        Enumerable.Empty<T>();
        // or Enumerable.Repeat(new T(), 10);
        // or even new T();
        // or foreach (var item in _list) {}
    }

    public void Run()
    {
        for (var i = 0; i < 8000000; i  )
        {
            if (_list.Any())
            // or if (_list.Count() > 0)
            // or if (_list.FirstOrDefault() != null)
            // or if (_list.SingleOrDefault() != null)
            // or other IEnumerable<T> method
            {
                return;
            }
        }
    }
}

Sonra boş olan türetilmiş bir sınıf var:

public class DerivedClass : BaseClass<object>
{
}

Hem sınıf ClassBase<T>.Run yöntem çalışan performansını ölçmek izin. Türetilmiş bir tür erişim; sınıf 4 kez daha yavaş. Ve bunun sebebini anlayamıyorum. Serbest modunda derlenmiş, sonuç ısınma ile aynıdır. Oluyor .NET 4.5.

public class Program
{
    public static void Main()
    {
        Measure(new DerivedClass());
        Measure(new BaseClass<object>());
    }

    private static void Measure(BaseClass<object> baseClass)
    {
        var sw = Stopwatch.StartNew();
        baseClass.Run();
        sw.Stop();
        Console.WriteLine(sw.ElapsedMilliseconds);
    }
}

Tam liste on gist

CEVAP
28 Kasım 2014, Cuma


Güncelleme:
Microsoft Connect CLR ekibinden bir cevap var

Paylaşılan jenerik kod sözlük aramaları ile ilgili. Çalışma zamanı ve TAM olarak sezgisel Peki bu özel test için çalışmıyor. Bu konuda neler yapılabilir bir göz atalım.

Bu arada, BaseClass için iki kukla yöntemleri (hatta adı olması gerekmez) ekleyerek bu geçici bir çözüm bulabilirsiniz. Sezgisel biri beklendiği gibi çalışmasına neden olacaktır.

Özgün:
Bu başarısız JİT.

Bu çılgın şey ile tedavi edilebilir:

    public class BaseClass<T>
    {
        private List<T> _list = new List<T>();

        public BaseClass()
        {
            Enumerable.Empty<T>();
            // or Enumerable.Repeat(new T(), 10);
            // or even new T();
            // or foreach (var item in _list) {}
        }

        public void Run()
        {
            for (var i = 0; i < 8000000; i  )
            {
                if (_list.Any())
                {
                    return;
                }
            }
        }

        public void Run2()
        {
            for (var i = 0; i < 8000000; i  )
            {
                if (_list.Any())
                {
                    return;
                }
            }
        }

        public void Run3()
        {
            for (var i = 0; i < 8000000; i  )
            {
                if (_list.Any())
                {
                    return;
                }
            }
        }
    }

Bu Run2 not()/Run3 ()değilher yerde aradı. Ama Run2 veya Run3 yöntemleri - performans ceza olarak önce alacaksın açıklama.

Bir şey ya da yöntem tablo boyutu, hizalama yığın ilişkili bir şey var sanırım.

P. S. değiştirebilirsiniz

 Enumerable.Empty<T>();
 // with
 var x = new Func<IEnumerable<T>>(Enumerable.Empty<T>);

hala aynı hata.

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

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • jpmkm1

    jpmkm1

    4 NİSAN 2008
  • KarnasCamillo

    KarnasCamill

    24 EKİM 2007
  • Matthew Pearce

    Matthew Pear

    9 AĞUSTOS 2009