Кроме того, это еще и дает прирост производительности, за счет того, что виртуальные вызовы для sealed классов могут оптимизироваться, и превращаться в невиртуальные.
В следующем примере я создал 10 виртуальных методов в базовом классе BaseClass. И эти функции переопределяются в классах DerSealedClass и DerNotSealedClass. DerSealedClass – это sealed класс, а DerNotSealedClass – нет.
Каждую итерацию цикла, вызываются все эти 10 методов у обоих классов.
Вот результаты теста для 100 000 000 итераций. Чем меньше времени потрачено – тем лучше!
Iterations: 100000000;
DerNotSealedClass: 357 ms;
DerSealedClass: 345 ms;
Как видите, разрыв небольшой, но все таки sealed классы работают быстрее.
Вот код теста:
using System;
using System.Diagnostics;
namespace TestTime
{
class Program
{
public class BaseClass
{
public virtual int Op0() { return 1; }
public virtual int Op1() { return 1; }
public virtual int Op2() { return 1; }
public virtual int Op3() { return 1; }
public virtual int Op4() { return 1; }
public virtual int Op5() { return 1; }
public virtual int Op6() { return 1; }
public virtual int Op7() { return 1; }
public virtual int Op8() { return 1; }
public virtual int Op9() { return 1; }
}
public sealed class DerSealedClass : BaseClass
{
public override int Op0() { return 2; }
public override int Op1() { return 2; }
public override int Op2() { return 2; }
public override int Op3() { return 2; }
public override int Op4() { return 2; }
public override int Op5() { return 2; }
public override int Op6() { return 2; }
public override int Op7() { return 2; }
public override int Op8() { return 2; }
public override int Op9() { return 2; }
}
public class DerNotSealedClass : BaseClass
{
public override int Op0() { return 3; }
public override int Op1() { return 3; }
public override int Op2() { return 3; }
public override int Op3() { return 3; }
public override int Op4() { return 3; }
public override int Op5() { return 3; }
public override int Op6() { return 3; }
public override int Op7() { return 3; }
public override int Op8() { return 3; }
public override int Op9() { return 3; }
}
private static void perfTest()
{
const int iterations = 100000000;
Stopwatch sw1;
Stopwatch sw2;
DerNotSealedClass notSealed = new DerNotSealedClass();
DerSealedClass Sealed = new DerSealedClass();
sw1 = Stopwatch.StartNew();
for (int i = 0; i < iterations; i++)
{
notSealed.Op0();
notSealed.Op1();
notSealed.Op2();
notSealed.Op3();
notSealed.Op4();
notSealed.Op5();
notSealed.Op6();
notSealed.Op7();
notSealed.Op8();
notSealed.Op9();
}
sw1.Stop();
sw2 = Stopwatch.StartNew();
for (int i = 0; i < iterations; i++)
{
Sealed.Op0();
Sealed.Op1();
Sealed.Op2();
Sealed.Op3();
Sealed.Op4();
Sealed.Op5();
Sealed.Op6();
Sealed.Op7();
Sealed.Op8();
Sealed.Op9();
}
sw2.Stop();
Console.WriteLine("Iterations: {0};", iterations);
Console.WriteLine("DerNotSealedClass: {0} ms;", sw1.Elapsed.Milliseconds);
Console.WriteLine("DerSealedClass: {0} ms;", sw2.Elapsed.Milliseconds);
}
static void Main(string[] args)
{
perfTest();
}
}
}
3 коммент.:
Добрый день! Спасибо очень интересная статья. У меня 4х ядерный проц. и результат несколько приятнее:
Iterations: 100000000;
DerNotSealedClass: 715 ms;
DerSealedClass: 230 ms;
Для продолжения нажмите любую клавишу . . .
С уважением Кирилл.
Интересные результаты. Спасибо.
Что интересно у меня компилятор не оптимизировал ни один из вызовов:
.method private hidebysig static void UseSealed(class TestTime.Program/DerSealedClass 'sealed') cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: callvirt instance int32 TestTime.Program/BaseClass::Op0()
IL_0006: pop
IL_0007: ret
} // end of method Program::UseSealed
.method private hidebysig static void UseNotSealed(class TestTime.Program/DerNotSealedClass notsealed) cil managed
{
// Code size 8 (0x8)
.maxstack 8
IL_0000: ldarg.0
IL_0001: callvirt instance int32 TestTime.Program/BaseClass::Op0()
IL_0006: pop
IL_0007: ret
} // end of method Program::UseNotSealed
Оба дергает как виртуальные
Отправить комментарий