SORU
29 AĞUSTOS 2011, PAZARTESİ


Performans &; doğrudan" C arabirimi çağrı vs sanal çağrı"#

This benchmark doğrudan sanal bir yöntem nesne başvurusu üzerine arama arabirimi başvurusu üzerine uygulayan çağrılması daha hızlı olduğunu göstermek için görünür.

Diğer bir deyişle:

interface IFoo {
    void Bar();
}

class Foo : IFoo {
    public virtual void Bar() {}
}

void Benchmark() {
    Foo f = new Foo();
    IFoo f2 = f;
    f.Bar(); // This is faster.
    f2.Bar();    
}

C dünyaya gelen bu çağrı, her ikisi de aynı (sanal tablo basit bir arama gibi) uygulanan ve aynı performansa sahip olacağını beklerdim. Nasıl yok C# sanal çağırır ve ne bu" görünüşe göre bir arayüz üzerinden arama zaman bitmiş olur iş mi? "ekstra uygulamak.

--- EDİT ---

TAMAM, cevap/yorum şimdiye kadar aldığım nesnenin arayüzü ile çift işaretçi çözümlemesi sanal çağrısına karşı sanal çağrı için sadece bir başvuru olduğu anlamına gelmez.

Yani biri açıklasın lütfennedenbu gerekli mi? C sanal tablo yapısını#? "C için tipik olarak () değil mi? düz C yapılan tasarım artıları ve eksileri ne# bu yol tasarım dili? Bu bir "", sadece gerekli olduğunu neden merak ettiğimi tasarım. kötü demiyorum

Özetle, çok isterimanlıyorumbenim aracı ben çok kaputun altında ne daha etkili bir şekilde kullanabilir. Ve "eğer" ya da "başka bir dil" cevap türleri. kullanan bilmen gerekmez mi artık tam anlayamadım eğer hiç memnun olurum

--- EDİT 2 ---

Sadece yapmak için açık değiliz ile ilgili bazı JİT derleyici optimizasyon buraya kaldırır dinamik gönderme: ben modifiye kriter söz asıl soru örneğini bir sınıf veya diğer rasgele de çalışma zamanı. Örnekleme derleme ve derleme yükleme sonra/JİTing sonra olur bu yana, dinamik her iki durumda da gönderme önlemek için bir yol yoktur

interface IFoo {
    void Bar();
}

class Foo : IFoo {
    public virtual void Bar() {
    }
}

class Foo2 : Foo {
    public override void Bar() {
    }
}

class Program {

    static Foo GetFoo() {
        if ((new Random()).Next(2) % 2 == 0)
            return new Foo();
        return new Foo2();
    }

    static void Main(string[] args) {

        var f = GetFoo();
        IFoo f2 = f;

        Console.WriteLine(f.GetType());

        // JIT warm-up
        f.Bar();
        f2.Bar();

        int N = 10000000;
        Stopwatch sw = new Stopwatch();

        sw.Start();
        for (int i = 0; i < N; i  ) {
            f.Bar();
        }
        sw.Stop();
        Console.WriteLine("Direct call: {0:F2}", sw.Elapsed.TotalMilliseconds);

        sw.Reset();
        sw.Start();
        for (int i = 0; i < N; i  ) {
            f2.Bar();
        }
        sw.Stop();
        Console.WriteLine("Through interface: {0:F2}", sw.Elapsed.TotalMilliseconds);

        // Results:
        // Direct call: 24.19
        // Through interface: 40.18

    }

}

--- EDİT 3 ---

Eğer ilgilenen olursa, burada benim Visual C 2010-miras çarpın diğer sınıflar bu sınıfın bir örneğini ortaya koyuyor:

Kod:

class IA {
public:
    virtual void a() = 0;
};

class IB {
public:
    virtual void b() = 0;
};

class C : public IA, public IB {
public:
    virtual void a() override {
        std::cout << "a" << std::endl;
    }
    virtual void b() override {
        std::cout << "b" << std::endl;
    }
};

Hata ayıklayıcısı:

c   {...}   C
    IA  {...}   IA
        __vfptr 0x00157754 const C::`vftable'{for `IA'} *
            [0] 0x00151163 C::a(void)   *
    IB  {...}   IB
        __vfptr 0x00157748 const C::`vftable'{for `IB'} *
            [0] 0x0015121c C::b(void)   *

Birden fazla sanal tablo işaretçi açıkça görülebilir, ve sizeof(C) == 8 (32-bit build).

...

C c;
std::cout << static_cast<IA*>(&c) << std::endl;
std::cout << static_cast<IB*>(&c) << std::endl;

..... yazdırır

0027F778
0027F77C

...aynı nesne içinde farklı arayüzleri işaretçileri gösteren aslında o nesnenin farklı kısımlarına işaret (yani farklı fiziksel adresleri içerir).

CEVAP
27 EYLÜL 2011, Salı


http://msdn.microsoft.com/en-us/magazine/cc163791.aspx makale sorularınıza cevap verecektir sanırım. Özellikle, bölüm Interface Vtable Map and Interface Map ve Sanal üzerinde aşağıdaki bölümde Gönderme bakın.

JİT derleyici şeyler ve basit davanız için kodu anlamaya optimize etmek için muhtemelen mümkün. Ama genel durumda değil.

IFoo f2 = GetAFoo();

GetAFoo IFoo JİT derleyici çağrı optimize etmek mümkün olmaz bir iade olarak tanımlanır.

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

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Andrea Lewis

    Andrea Lewis

    14 Mart 2013
  • Jordie Jordan

    Jordie Jorda

    27 Ocak 2008
  • TechBalance

    TechBalance

    12 HAZİRAN 2011