본문 바로가기
C++ 200제/코딩 IT 정보

C# Sealed 클래스, 성능 향상 최적화 방법 (추상 키워드 예제)

by vicddory 2017. 4. 14.

C# Sealed 클래스, 성능 향상 최적화 방법 (추상 키워드 예제)


Sealed. Sealed 클래스는 상속되지 않으며, 키워드로 사용한다면 함수 호출 시 성능 향상이 됩니다.


1. 상속되지 않는 특성

2. 특정 상황에서 성능이 향상


이 두 가지 특징을 갖는 키워드라 할 수 있습니다.


Example. sealed 키워드가 적용되면 C# 컴파일러는 당신의 클래스 어셈블리에 "sealed" 메타 데이터를 적용시킵니다. 상위 클래스에선 sealed 키워드가 선언된 클래스를 상속 받을수 없도록 제한합니다. (syntax hint)


Tip: JIT 컴파일러는 sealed 메타 데이터를 이용해 함수 호출을 최적화할 수 있습니다.


The two classes. ITest 인터페이스를 구현하는 두 클래스엔 약간의 차이가 있습니다. GetNumber() 함수(테스트용)가 리턴하는 정수와 TestB 클래스에 추가된 sealed 키워드입니다.

Next: 함수 하나를 갖는 인터페이스(ITest)와 두 개의 클래스가 있습니다. 여기서, 첫번째 클래스인 TestA는 sealed 클래스가 아니지만, 두번째 클래스인 TestB는 sealed 클래스입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
using System;
/// <summary>
/// Example interface.
/// </summary>
interface ITest
{
    /// <summary>
    /// Method required by the interface.
    /// </summary>
    int GetNumber();
}
 
/// <summary>
/// Non-sealed class that implements an interface.
/// </summary>
class TestA : ITest
{
    /// <summary>
    /// Interface implementation.
    /// </summary>
    public int GetNumber()
    {
        return 1;
    }
}
 
/// <summary>
/// Sealed class that implements an interface.
/// </summary>
sealed class TestB : ITest
{
    /// <summary>
    /// Interface implementation.
    /// </summary>
    public int GetNumber()
    {
        return 2;
    }
}
 
class Program
{
    static void Main()
    {
        ITest test1 = new TestA(); // Regular class
        ITest test2 = new TestB(); // Sealed instantiation
 
        Console.WriteLine(test1.GetNumber()); // TestA.GetNumber
        Console.WriteLine(test2.GetNumber()); // TestB.GetNumber
    }
}
cs

 

Output


1

2


Discussion. .NET 프레임워크가 인터페이스 함수와 가상 함수를 호출할 때, 어떤 메커니즘의 차이가 있을까요? 클래스의 다형성(polymorphism)을 지원하기 위해 프로그램 언어는 가상의 디스패치 테이블이 담긴 함수를 생성합니다.

Then. 이후 런타임 시점에 이 함수를 찾는데, .NET 프레임워크에는 각 타입별 포인터를 보유하게 됩니다. (.NET 프레임워크에서 관리하는 영역을 managed heap) 포인터들은 가상 함수 디스패치에 사용됩니다.


Also, JIT(just-in-time) 최적화 기능은 실행 환경에 따라 수행되지 않을 수도 있습니다. 비주얼 스튜디오로 프로그램을 실행하면 sealed는 최적화되지 않습니다.


However. 다른 디버거를 이용해 외부에서 프로그램을 실행하면 최적화가 됩니다.


JIT 최적화 및 디버깅 : https://msdn.microsoft.com/ko-kr/library/ms241594.aspx


모듈을 로드할 때 JIT 최적화 기능 사용 안 함 옵션을 해제하면 최적화된 JIT 코드를 디버깅할 수 있지만 최적화된 코드와 소스 코드 사이의 불일치로 인해 디버깅 기능이 제한될 수도 있습니다.


C# Sealed 클래스, 성능 향상 최적화 방법 (Sealed class)


Benckmark. sealed 키워드를 이용하면 성능 향상이 됩니다. 아래 벤치마킹 결과에 따르면 인터페이스 함수를 상속받는 두 클래스 중 sealed로 선언된 클래스의 속도가 약 1/3 가량 빨랐습니다.


Tip. 인터페이스가 많은 프로그램일수록 sealed를 사용하면 함수 호출 속도를 향상할 수 있습니다.


Outer variables used in benchmark

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int sum1 = 0;
int sum2 = 0;
ITest test1 = new TestA();
ITest test2 = new TestB();
 
Contents of tight loops
 
sum1 += test1.GetNumber(); // Loop 1 body
sum1 += test1.GetNumber();
sum1 += test1.GetNumber();
sum1 += test1.GetNumber();
sum1 += test1.GetNumber();
sum2 += test2.GetNumber(); // Loop 2 body
sum2 += test2.GetNumber();
sum2 += test2.GetNumber();
sum2 += test2.GetNumber();
sum2 += test2.GetNumber();
cs

 

Results


Iterations:                1000000 * 100

TestA.GetNumber (regular): 2.490 ns

TestB.GetNumber (sealed):  2.162 ns [faster]


In this benchmark. 똑같이 다섯번의 함수 호출이 이뤄집니다. 이를 고려하여 누적된 결과는 5로 나누어 나노초로 변환했습니다.


Summary. 위에서 C#의 sealed 키워드를 살펴봤습니다. 함수 호출 시간 단축에 유용한 이 키워드를 클래스에 적용하여 성능 향상을 확인해 봤습니다. sealed는 성능상의 이점이 있지만, 프로그램 실행 환경에 따라 결과는 다를 수 있습니다.


출처 - C# Sealed Keyword

C# Sealed 클래스, 성능 향상 최적화 방법 (추상 키워드 예제)

댓글