Здравствуйте, 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>>
Здравствуйте, eugen1001, Вы писали:
TK>>Можно написать простейший тест и, посмотреть самому...
E>Тест написал. По его результатам коэффициенты немного различаются от заявленны (FW 2.0):
E>E>Виртуальный метод класса: 8589935154
E>Шаблонный виртуальный метод к: 68719480845
E>
Ну, я же и не говорил, что на мои коэффициэнты молиться надо

Между тем, разница в 8 раз все равно показательна.
PS
Почему бы не использовать готовый класс из framework — System.Diagnostics.Stopwatch?
Если у Вас нет паранойи, то это еще не значит, что они за Вами не следят.
Здравствуйте, TK, Вы писали:
TK>Ну, я же и не говорил, что на мои коэффициэнты молиться надо
Между тем, разница в 8 раз все равно показательна.
Меня больше поразило, что вызов простого и виртуального метода совпали
Надо переделать тест

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

Спасибо за науку.
Код по замеры просто взял из чужого примера

... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Здравствуйте, Nimnul, Вы писали:
N>Ты не учел только одного, что команды на конвеер подаются со скоростью системной шины, много это или мало решать тебе
По твоему — на сколько я ошибся?
Здравствуйте, Alexander_fx, Вы писали:
A_>Ok — с этими фичами знаком — только не знал что это так называется.
A_>Спасибо.
Я что-ли знал? Открыл msdn и посмотрел.