Re[4]: Есть ли разница в быстродействии???
От: eugen1001  
Дата: 17.10.06 16:46
Оценка:
Здравствуйте, TK, Вы писали:

TK>Можно написать простейший тест и, посмотреть самому...


Тест написал. По его результатам коэффициенты немного различаются от заявленны (FW 2.0):

Метод класса:                    8589935155
Виртуальный метод класса:        8589935154
Шаблонный метод класса:          8589935155
Шаблонный виртуальный метод к:  68719480845
Метод интерфейса:               12884902529
Метод шаблона:                   8589935154
Виртуальный метод шаблона:       8589935139
Шаблонный метод шаблона:         8589935170
Виртуальный шаблонный метод ш:  68719480846
Метод интерфейса шаблона:       12884902513
Метод с параметром generic-ин:   8589935232
Шаблонный метод generic-интер:  68719480846



Также я проанализировал assembler для случая "Шаблонный виртуальный метод к":

00000067  push        0A29BD0h 
0000006c  mov         ecx,edi 
0000006e  mov         edx,0A299E8h 
00000073  call        791949BF // этот вызов похоже и вычисляет адрес функции вызова, и делает это не быстро.
00000078  mov         esi,eax 
0000007a  mov         ecx,edi 
0000007c  call        esi



И вот код теста:

namespace TestCallMethods
{
    public class TestBase 
    {
        public const int Times = 100000000;

        [System.Runtime.InteropServices.DllImport("KERNEL32")]
        public static extern bool QueryPerformanceCounter(
            ref long lpPerformanceCount);

        [System.Runtime.InteropServices.DllImport("KERNEL32")]
        public static extern bool QueryPerformanceFrequency(
            ref long lpFrequency);

        [System.Runtime.InteropServices.DllImport("KERNEL32")]
        public static extern UInt64 GetTickCount();
    }

    public class Program
    {
        static void Main(string[] args)
        {
            Console.ReadLine();
            TestNoneTemplate.Test();
            TestTemplate.Test();
            Console.ReadLine();
        }
    }
    public interface IBase
    {
        void Foo();
    }

    public class Base : IBase
    {
        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        public virtual void Foo()
        {
        }

        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        public void FooS()
        {
        }

        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        public virtual void FooT<T>()
        {
        }

        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        public void FooTS<T>()
        {
        }
    }

    public class Derived : Base
    {
        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        public override void Foo()
        {
        }

        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        public override void FooT<T>()
        {
        }
    }

    public class TestNoneTemplate
    {
        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        public static void Test()
        {
            TestBS();

            TestBV();

            TestBTS();

            TestBT();

            TestIB();
        }

        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        private static void TestBS()
        {
            Console.Write("Метод класса:                  ");
            UInt64 oldTick = TestBase.GetTickCount();
            Base bs = new Base();
            for (int i = 0; i < TestBase.Times; i++)
            {
                bs.FooS();
            }
            UInt64 dTick = TestBase.GetTickCount() - oldTick;
            Console.WriteLine(dTick.ToString().PadLeft(12));
        }

        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        private static void TestBV()
        {
            Console.Write("Виртуальный метод класса:      ");
            UInt64 oldTick = TestBase.GetTickCount();
            Base bv = new Derived();
            for (int i = 0; i < TestBase.Times; i++)
            {
                bv.Foo();
            }
            UInt64 dTick = TestBase.GetTickCount() - oldTick;
            Console.WriteLine(dTick.ToString().PadLeft(12));
        }    

        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        private static void TestBTS()
        {
            Console.Write("Шаблонный метод класса:        ");
            UInt64 oldTick = TestBase.GetTickCount();
            Base bts = new Derived();
            for (int i = 0; i < TestBase.Times; i++)
            {
                bts.FooTS<int>();
            }
            UInt64 dTick = TestBase.GetTickCount() - oldTick;
            Console.WriteLine(dTick.ToString().PadLeft(12));
        }    

        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        private static void TestBT()
        {
            Console.Write("Шаблонный виртуальный метод к: ");
            UInt64 oldTick = TestBase.GetTickCount();
            Base bt = new Derived();
            for (int i = 0; i < TestBase.Times; i++)
            {
                bt.FooT<int>();
            }
            UInt64 dTick = TestBase.GetTickCount() - oldTick;
            Console.WriteLine(dTick.ToString().PadLeft(12));
        }    

        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        private static void TestIB()
        {
            Console.Write("Метод интефейса:               ");
            UInt64 oldTick = TestBase.GetTickCount();
            IBase ib = new Derived();
            for (int i = 0; i < TestBase.Times; i++)
            {
                ib.Foo();
            }
            UInt64 dTick = TestBase.GetTickCount() - oldTick;
            Console.WriteLine(dTick.ToString().PadLeft(12));
        }    
    }
    public interface IBaseT<T>
    {
        void Foo<T>();
        void Foo(T t);
    }

    public class BaseT<T> : IBaseT<T>, IBase
    {
        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        public virtual void Foo()
        {
        }

        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        public void FooS()
        {
        }

        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        public virtual void FooT<T>()
        {
        }

        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        public void FooTS<T>()
        {
        }

        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        public virtual void Foo<T>()
        {
        }

        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        public virtual void Foo(T t)
        {
        }
    }

    public class DerivedT<T> : BaseT<T>
    {
        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        public override void Foo()
        {
        }

        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        public override void FooT<T>()
        {
        }

        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        public override void Foo<T>()
        {
        }

        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        public override void Foo(T t)
        {
        }
    }

    public class TestTemplate
    {
        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        public static void Test()
        {
            TestBS();

            TestBV();

            TestBTS();

            TestBVTS();

            TestIB();

            TestIBTP();

            TestITBTP();
        }

        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        private static void TestBS()
        {
            Console.Write("Метод шаблона:                 ");
            UInt64 oldTick = TestBase.GetTickCount();
            BaseT<int> bs = new DerivedT<int>();
            for (int i = 0; i < TestBase.Times; i++)
            {
                bs.FooS();
            }
            UInt64 dTick = TestBase.GetTickCount() - oldTick;
            Console.WriteLine(dTick.ToString().PadLeft(12));
        }

        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        private static void TestBV()
        {
            Console.Write("Виртуальный метод шаблона:     ");
            UInt64 oldTick = TestBase.GetTickCount();
            BaseT<int> b = new DerivedT<int>();
            for (int i = 0; i < TestBase.Times; i++)
            {
                b.Foo();
            }
            UInt64 dTick = TestBase.GetTickCount() - oldTick;
            Console.WriteLine(dTick.ToString().PadLeft(12));
        }

        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        private static void TestBTS()
        {
            Console.Write("Шаблонный метод шаблона:       ");
            UInt64 oldTick = TestBase.GetTickCount();
            BaseT<int> bts = new DerivedT<int>();
            for (int i = 0; i < TestBase.Times; i++)
            {
                bts.FooTS<int>();
            }
            UInt64 dTick = TestBase.GetTickCount() - oldTick;
            Console.WriteLine(dTick.ToString().PadLeft(12));
        }

        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        private static void TestBVTS()
        {
            Console.Write("Виртуальный шаблонный метод ш: ");
            UInt64 oldTick = TestBase.GetTickCount();
            BaseT<int> bt = new DerivedT<int>();
            for (int i = 0; i < TestBase.Times; i++)
            {
                bt.FooT<int>();
            }
            UInt64 dTick = TestBase.GetTickCount() - oldTick;
            Console.WriteLine(dTick.ToString().PadLeft(12));
        }

        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        private static void TestIB()
        {
            Console.Write("Метод интерфейса шаблона:      ");
            UInt64 oldTick = TestBase.GetTickCount();
            IBase ib = new DerivedT<int>();
            for (int i = 0; i < TestBase.Times; i++)
            {
                ib.Foo();
            }
            UInt64 dTick = TestBase.GetTickCount() - oldTick;
            Console.WriteLine(dTick.ToString().PadLeft(12));
        }

        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        private static void TestIBTP()
        {
            Console.Write("Метод с параметром generic-ин: ");
            UInt64 oldTick = TestBase.GetTickCount();
            IBaseT<int> ibt = new DerivedT<int>();
            for (int i = 0; i < TestBase.Times; i++)
            {
                ibt.Foo(0);
            }
            UInt64 dTick = TestBase.GetTickCount() - oldTick;
            Console.WriteLine(dTick.ToString().PadLeft(12));
        }

        [System.Runtime.CompilerServices.MethodImpl(MethodImplOptions.NoInlining)]
        private static void TestITBTP()
        {
            Console.Write("Шаблонный метод generic-интер: ");
            UInt64 oldTick = TestBase.GetTickCount();
            IBaseT<int> tibt = new DerivedT<int>();
            for (int i = 0; i < TestBase.Times; i++)
            {
                tibt.Foo<int>();
            }
            UInt64 dTick = TestBase.GetTickCount() - oldTick;
            Console.WriteLine(dTick.ToString().PadLeft(12));
        }
    }
}
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[5]: Есть ли разница в быстродействии???
От: TK Лес кывт.рф
Дата: 17.10.06 20:07
Оценка:
Здравствуйте, eugen1001, Вы писали:

TK>>Можно написать простейший тест и, посмотреть самому...


E>Тест написал. По его результатам коэффициенты немного различаются от заявленны (FW 2.0):


E>
E>Виртуальный метод класса:        8589935154
E>Шаблонный виртуальный метод к:  68719480845
E>


Ну, я же и не говорил, что на мои коэффициэнты молиться надо Между тем, разница в 8 раз все равно показательна.


PS
Почему бы не использовать готовый класс из framework — System.Diagnostics.Stopwatch?
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Re[6]: Есть ли разница в быстродействии???
От: eugen1001  
Дата: 18.10.06 07:18
Оценка:
Здравствуйте, TK, Вы писали:

TK>Ну, я же и не говорил, что на мои коэффициэнты молиться надо Между тем, разница в 8 раз все равно показательна.

Меня больше поразило, что вызов простого и виртуального метода совпали
Надо переделать тест .


TK>PS

TK>Почему бы не использовать готовый класс из framework — System.Diagnostics.Stopwatch?

Ну это по не знанию Спасибо за науку.
Код по замеры просто взял из чужого примера
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[2]: Есть ли разница в быстродействии???
От: Dufrenite Дания  
Дата: 18.10.06 17:06
Оценка:
Здравствуйте, Nimnul, Вы писали:

N>Ты не учел только одного, что команды на конвеер подаются со скоростью системной шины, много это или мало решать тебе


По твоему — на сколько я ошибся?
Re[7]: Есть ли разница в быстродействии???
От: Lloyd Россия  
Дата: 19.10.06 06:26
Оценка: :)
Здравствуйте, Alexander_fx, Вы писали:

A_>Ok — с этими фичами знаком — только не знал что это так называется.

A_>Спасибо.

Я что-ли знал? Открыл msdn и посмотрел.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.