C#

C# 기초부터 고급까지 Chapter 3.5. 코드 분석 및 성능 측정 도구 사용 (BenchmarkDotNet 등)

Juan_ 2025. 5. 7. 20:43
728x90

📘 Chapter 3.5: 코드 분석 및 성능 측정 도구 사용 (BenchmarkDotNet 등)


✅ 이 챕터에서 배울 것

  • 왜 성능 측정이 중요한가
  • BenchmarkDotNet 사용법 (실전 예제 포함)
  • 간단한 Stopwatch 성능 측정 방법
  • GC, Memory 관련 측정
  • 실무 상황에서 벤치마크 전략
  • 예: for vs foreach, StringBuilder vs +

1️⃣ 왜 성능 측정이 중요한가?

"느릴 것 같아서 바꿨는데, 더 느려짐"
→ 실무에서 흔한 일이다

✅ 체감 성능 ≠ 실제 성능

  • 컴파일러 최적화
  • GC 개입
  • JIT 예열 등으로 오차 생김

→ 그러니까 정확한 측정 도구로 정량 분석해야 된다!


2️⃣ BenchmarkDotNet – .NET 성능 측정의 정석

https://benchmarkdotnet.org

✅ 설치

dotnet add package BenchmarkDotNet

✅ 기본 템플릿 예제

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;

public class MyBenchmark
{
    private List<int> _list = Enumerable.Range(0, 1000).ToList();

    [Benchmark]
    public void ForLoop()
    {
        for (int i = 0; i < _list.Count; i++)
        {
            var val = _list[i];
        }
    }

    [Benchmark]
    public void ForeachLoop()
    {
        foreach (var item in _list)
        {
            var val = item;
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        BenchmarkRunner.Run<MyBenchmark>();
    }
}

✅ 실행하면 bin/Release/netX.X/BenchmarkDotNet.Artifacts 안에 결과 출력됨!

🔍 결과 예시

MethodMeanErrorGen 0Allocated
ForLoop2.345 us±0.0050.000 B
ForeachLoop2.158 us±0.0040.000 B

➡️ 오차 범위까지 포함된 정밀 결과 제공
➡️ GC 할당도 확인 가능!


3️⃣ 간단한 측정: Stopwatch

var sw = Stopwatch.StartNew();

for (int i = 0; i < 1000000; i++)
{
    var x = i * 2;
}

sw.Stop();
Console.WriteLine($"⏱ 실행 시간: {sw.ElapsedMilliseconds} ms");

🟡 간단하지만:

  • GC 개입
  • 최적화 여부
  • Warm-up 안 됨

정확한 비교용으론 BenchmarkDotNet이 낫다!


4️⃣ 실전: StringBuilder vs 문자열 +

public class StringBenchmark
{
    [Benchmark]
    public string StringPlus()
    {
        string result = "";
        for (int i = 0; i < 100; i++)
        {
            result += i;
        }
        return result;
    }

    [Benchmark]
    public string UseStringBuilder()
    {
        var sb = new StringBuilder();
        for (int i = 0; i < 100; i++)
        {
            sb.Append(i);
        }
        return sb.ToString();
    }
}

✅ 대부분의 경우 StringBuilder가 훨씬 빠르다
하지만 반복 횟수가 작으면 큰 차이 안 나기도 한다


5️⃣ GC, 메모리 측정도 가능

[MemoryDiagnoser]
public class GCBenchmark
{
    [Benchmark]
    public void AllocateList()
    {
        var list = new List<int>();
        for (int i = 0; i < 1000; i++)
        {
            list.Add(i);
        }
    }
}

📌 출력에 Gen0, Gen1, Allocated 값까지 포함됨


✅ 실무 팁: 벤치마크 전략

상황전략
성능 비교반드시 BenchmarkDotNet으로 테스트
GC 개입 확인[MemoryDiagnoser] 어노테이션 추가
반복 횟수 적정화실제 사용 상황과 유사하게
결과 해석평균 + 표준편차 함께 보기
Warm-up초기 1~2회 측정값은 버리는게 좋음

✅ 정리 요약

항목요약
BenchmarkDotNet가장 정확한 .NET 벤치마킹 도구
Stopwatch빠르게 비교할 때만 사용
MemoryDiagnoserGC 할당량까지 확인 가능
실무 적용반복문, 문자열, 알고리즘 등 성능 튜닝

📢 다음 챕터 예고 🎓

다음 챕터주제
Chapter 3.6.NET 메모리 관리 이해 – GC 동작 원리
728x90