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

C# 함수 오버로딩 예제로 성능 향상 확인하기 method overload

by vicddory 2019. 3. 14.

C# 메서드 오버로드로 최적화되는지 확인하기 IL



Overload. 오버로드 된 메서드는 코드의 가독성을 높입니다. 프로그램 규모가 커지고 설계가 복잡해질수록 변경되는 코드는 많아집니다. 그래서 코드 변경 지침이 필요하게 됩니다. 「메소드 오버로드를 사용하면」, 복잡성을 줄여 일부 성능을 향상할 수 있습니다.


C# 함수 오버로딩 예제로 성능 향상 확인하기 (method overload)[객체지향 프로그래밍 oop 다형성 예제]




첫 번째 예제. 오버로딩 함수들은 컴파일된 프로그램에서 독립적입니다. 아래 소스엔 같은 이름을 가진 함수가 2개 있습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Program
{
    static void Main()
    {
        MethodA();
        MethodA("");
    }
 
    static void MethodA()
    {
    }
 
    static void MethodA(string a)
    {
    }
}
cs


두 번째 예제. 위 메소드 예제에는 한 가지 문제가 있습니다. 코드의 가독성과 성능을 향상할 순 있지만, 함수를 호출할 땐 비효율적이고 헷갈릴 수 있습니다.

그래서 string.Empty를 인수로 사용합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
using System;
 
class Program
{
    public static void Main()
    {
        ShowString(string.Empty);
        ShowString("Category");
    }
 
    static void ShowString(string value)
    {
        if (value == string.Empty)
        {
            Console.WriteLine("Popular");
        }
        else
        {
            Console.WriteLine(value);
        }
    }
}
cs


c# 오버로드 overload 메소드 함수[객체지향 프로그래밍 oop 다형성 예제]


세 번째 예제. 위 코드는 불필요한 분기문을 갖고 있습니다. 분기 예측을 위해서라면 아래의 오버로딩 예도 좋을 수 있습니다. (좋을 수도 있지만, 좋지 않을 수도 있다는 중의적 의미)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using System;
 
class Program
{
    public static void Main()
    {
        ShowString();
        ShowString("Category");
    }
 
    static void ShowString()
    {
        // Send default argument to overload.
        ShowString("Popular");
    }
 
    static void ShowString(string value)
    {
        // We don't need an if check here, which makes
        // ... calling this method directly faster.
        Console.WriteLine(value);
    }
}
cs


Internals. 오버로딩 된 함수가 컴파일 되는 시점의 중간 언어를 확인합니다. if 문을 가졌던 ShowString 메소드를 살펴봅니다.



C# 메서드 오버로드로 최적화되는지 확인하기 IL[객체지향 프로그래밍 oop 다형성 예제]


오버로드 되지 않았을 경우 : IL


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.method private hidebysig static void ShowString (string 'value') cil managed
{
// 코드 사이즈 31 (0x1f)
    .maxstack 8
    IL_0000 : ldarg.0
    IL_0001 : ldsfld string [mscorlib] System.String :: Empty
    IL_0006 : call bool [mscorlib] System.String :: op_Equality (stringstring)
 
    IL_000b : brfalse.s IL_0018
    IL_000d : ldstr "Popular"
    IL_0012 : call void [mscorlib] System.Console :: WriteLine (string)
    IL_0017 : ret
    IL_0018 : ldarg.0
    IL_0019 : call void [mscorlib] System.Console :: WriteLine (string)
    IL_001e : ret
}
cs


ShowString의 if 체인 op_Equality가 사용되었습니다. 하지만, JIT (Just in Time) 컴파일 단계에서 최적화 되지 않았습니다.


그럼 메소드가 오버로드된 경우는 어떨까요?


오버로드 사용했을 경우 : IL


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.method public hidebysig specialname rtspecialname
        instance void  .ctor() cil managed
{
 // Code size       22 (0x16)
 .maxstack  8
 IL_0000:  ldarg.0
 IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
 IL_0006:  call       void OverloadA::ShowString()
 IL_000b:  ldstr      "Category"
 IL_0010:  call       void OverloadA::ShowString(string)
 IL_0015:  ret
}
 
.method private hidebysig static void  ShowString() cil managed
{
  // Code size       11 (0xb)
  .maxstack  8
  IL_0000:  ldstr      "Popular"
  IL_0005:  call       void OverloadA::ShowString(string)
  IL_000a:  ret
}
cs


오버로딩된 ShowString 함수는 if else 체인(연관성)이 필요하지 않습니다. 컴파일러가 확인할 필요도 없어서 코드가 효율적입니다. 메서드 오버로드를 사용하기 위해 코드 리펙토링 필요성을 확인할 수 있습니다.


코드 간소화, 성능 향상을 위해 메소드 오버로드가 필요할까요? 네 필요합니다.



덧글. 예제 자체를 이해하는데 시간이 좀 걸렸네요. 참 오묘해요.


C# 메서드 오버로드로 최적화되는지 확인하기 IL

written by vicddory