Zerolog 쓰기 방식에 따른 성능 평가

Zerolog 쓰기 방식에 따른 성능 평가

이 글에서는 .NET에서 Zerolog을 기반으로 동기 방식과 인터페이스 기반 로깅 방식을 사용했을 때의 성능 차이를 평가하고, 각 방식의 장단점과 사용 환경에 따른 선택 기준을 제시합니다.

테스트 결과

로깅 방식평균 시간(ms)
직접 호출257.2
인터페이스 기반 호출316

테스트 방법

  • 동일한 조건 하에 500,000개의 로그 메시지를 기록
  • 5회 반복하여 평균 시간을 산출
  • 성능 측정을 위해 .NET의 Stopwatch 클래스 사용

테스트 코드

직접 호출

var path = $@"/logs/zerolog.log";
var elapsedList = new List<long>();
LogManager.Initialize(new ZeroLogConfiguration
        {
            LogMessagePoolSize = 10000000,
            RootLogger = {
                    Appenders = {
                        new DateAndSizeRollingFileAppender(path)
                    }
                }
        });
        
var logger = LogManager.GetLogger(nameof(ZeroLogger));
for (int c = 0; c < 5; c++)
{
    var sw = Stopwatch.StartNew();
    for (int i = 0; i < 500_000; i++)
        logger.Info($"Log Performance Test. No : {c}.{i}. elapsed : {sw.ElapsedMilliseconds}");
    LogManager.Flush();
    elapsedList.Add(sw.ElapsedMilliseconds);
}
Console.WriteLine($"Elapsed Time : {elapsedList.Average()}");
// Elapsed Time : 257.2

인터페이스 기반 호출

var path = $@"/logs/zerolog.log";
var elapsedList = new List<long>();
var logger = LoggingFactory.CreateLogger("Zero");
logger.Init(path);
for (int c = 0; c < 5; c++)
{
    var sw = Stopwatch.StartNew();
    for (int i = 0; i < 500_000; i++)
        logger.Information($"Log Performance Test. No : {c}.{i}. elapsed : {sw.ElapsedMilliseconds}");
    LogManager.Flush();
    elapsedList.Add(sw.ElapsedMilliseconds);
}
Console.WriteLine($"Elapsed Time : {elapsedList.Average()}");
// Elapsed Time : 2350.8
public interface ILogging
{
    void Init(string path);
    void Information(string message);
}
public class LoggingFactory
{
    public static ILogging CreateLogger(string logType)
    {
        return logType switch
        {
            "File" => new FileLogger(),
            "Zero" => new ZeroLogger(),
            _ => throw new ArgumentException($"Invalid log type: {logType}")
        };
    }
}
public class ZeroLogger : ILogging
{
    private ZeroLog.Log _logger;
    public void Init(string path)
    {        
        LogManager.Shutdown();
        LogManager.Initialize(new ZeroLogConfiguration
        {
            LogMessagePoolSize = 10000000,
            RootLogger = {
                    Appenders = {
                        new DateAndSizeRollingFileAppender(path)
                    }
                }
        });
        _logger = LogManager.GetLogger(nameof(ZeroLogger));
    }
    public void Information(string message) => _logger?.Info(message);
}

결과 해석

Zerolog은 고성능을 목표로 하는 로그 라이브러리로, 로그 처리 중 발생하는 오버헤드를 최소화하도록 설계되었습니다. 성능 테스트 결과, 직접 호출 방식과 인터페이스 기반 호출 방식 모두 로그 메시지를 효율적으로 기록할 수 있었으며, 성능 차이는 크지 않습니다.

로깅 방식별 장단점

동기 방식

  • 장점: 성능이 뛰어나고, 간단한 구조로 인해 빠르게 처리됩니다.
  • 단점: 유지보수성이나 확장성 측면에서는 다소 제한적입니다.

인터페이스 기반 방식

  • 장점: - 다형성을 제공하여 여러 로깅 구현체를 쉽게 추가하거나 교체할 수 있으며, 구조적인 유연성이 높습니다. 인터페이스 기반의 방식에서도 성능이 충분히 뛰어나기 때문에, 일반적인 애플리케이션에서 실용적으로 사용할 수 있습니다.
  • 단점: 직접 호출 방식에 비해 약간의 성능 저하가 있지만, 이는 실제 애플리케이션에서 거의 눈에 띄지 않을 정도입니다.

맺음말

애플리케이션의 요구사항에 따라 적절한 로깅 방식을 선택하는 것이 중요합니다. 실시간 처리 시스템이나 성능이 최우선인 시스템에서는 동기 방식이 적합하고, 유지보수성과 확장성이 중요한 시스템에서는 인터페이스 기반 방식이 더 적합합니다. 성능과 구조적 유연성 사이의 균형을 고려하여 로깅 방식을 선택하는 것이 바람직합니다.