воскресенье, 15 марта 2009 г.

sealed классы работают быстрее... не намного, но быстрее!

Конечно же, если вы отмечаете свой класс как sealed, это говорит о том, что вы хотите запретить наследоваться от тех классов, которые не предназначены быть базовыми. Это избавляет разработчика от лишней головной боли.
Кроме того, это еще и дает прирост производительности, за счет того, что виртуальные вызовы для 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 коммент.:

Unknown комментирует...

Добрый день! Спасибо очень интересная статья. У меня 4х ядерный проц. и результат несколько приятнее:
Iterations: 100000000;
DerNotSealedClass: 715 ms;
DerSealedClass: 230 ms;
Для продолжения нажмите любую клавишу . . .
С уважением Кирилл.

DmytroZ комментирует...

Интересные результаты. Спасибо.

Анонимный комментирует...

Что интересно у меня компилятор не оптимизировал ни один из вызовов:

.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

Оба дергает как виртуальные

Отправить комментарий

 

.NET ate my MOSK;. Powered By Blogger © 2009 Bombeli | Theme Design: ooruc