Booil Jung

단일 호스트 실시간 애플리케이션을 위한 논블로킹 로그 기술

현대의 컴퓨팅 환경에서 실시간 애플리케이션의 중요성은 그 어느 때보다 강조되고 있습니다. 금융 거래 시스템, 산업 자동화 제어, 통신 인프라, 고성능 웹 서비스 등 응답 시간의 지연이 치명적인 서비스 실패로 이어질 수 있는 분야가 급격히 확대되고 있습니다. 이러한 시스템에서 로깅은 시스템의 상태를 모니터링하고, 장애를 진단하며, 성능을 분석하는 데 필수적인 요소입니다. 그러나 전통적인 로깅 방식은 실시간 시스템의 핵심 요구사항인 예측 가능하고 낮은 지연 시간(latency)을 심각하게 저해하는 주요 원인이 될 수 있습니다.

본 보고서는 단일 호스트 컴퓨터 환경에서 운영되는 실시간 애플리케이션을 대상으로, 기존 로깅 기술의 한계를 분석하고 장애나 블로킹(blocking) 문제를 회피하기 위한 고성능 논블로킹(non-blocking) 로그 기술을 심층적으로 분석하는 것을 목표로 합니다. 이를 위해 동기식 로깅의 근본적인 문제점부터 시작하여, 이를 해결하기 위한 비동기 아키텍처, 극단적인 성능을 추구하는 잠금 없는(lock-free) 자료 구조, I/O 최적화 기법, 그리고 시스템 전반을 관찰하는 커널 트레이싱 기술에 이르기까지 광범위한 주제를 다룰 것입니다. 본 보고서는 각 기술의 아키텍처 원리, 성능 특성, 그리고 장단점을 상세히 분석하여 시스템 아키텍트와 성능 엔지니어가 특정 실시간 요구사항에 가장 적합한 로깅 전략을 수립하는 데 필요한 이론적 기반과 실질적인 지침을 제공하고자 합니다.

로깅 기술을 논하기에 앞서, ‘실시간(real-time)’이라는 용어의 의미를 명확히 정의할 필요가 있습니다. 실시간 시스템은 연산의 논리적 정확성뿐만 아니라 연산이 완료되는 시간적 정확성까지 보장해야 하는 시스템을 의미합니다. 이러한 시스템은 마감 시간(deadline) 준수 여부에 따라 크게 두 가지로 분류됩니다.

이러한 시스템의 성능을 평가하는 핵심 지표는 지연 시간(latency), 즉 특정 작업이 완료되는 데 걸리는 시간, 지터(jitter), 즉 지연 시간의 변동성, 그리고 처리량(throughput), 즉 단위 시간당 처리할 수 있는 작업의 양입니다.1 고성능 로깅 기술은 이 세 가지 지표, 특히 지연 시간과 지터를 최소화하는 데 초점을 맞춥니다.

전통적인 로깅 방식은 애플리케이션의 실행 스레드 내에서 로그 메시지를 직접 파일, 데이터베이스, 콘솔 등 최종 저장소에 기록하는 동기식(synchronous) 모델을 따릅니다. 이러한 방식은 구현이 간단하지만 실시간 시스템에서는 결코 사용할 수 없는 치명적인 결함을 내포하고 있습니다.

단일 호스트 내에서도 고성능 로깅은 일종의 소형 분산 시스템 문제로 접근해야 합니다. 애플리케이션 스레드를 하나의 서비스로, 실제 I/O를 처리하는 로거 스레드를 또 다른 서비스로 간주할 수 있습니다. 이 두 서비스 간의 통신은 스레드 간 통신 메커니즘(예: 큐)을 통해 이루어지며, 이 통신 채널 자체의 성능이 전체 시스템의 성능을 좌우하게 됩니다. 애플리케이션 스레드가 로그 메시지를 생성(produce)하고 로거 스레드가 이를 소비(consume)하는 구조에서, 핵심 과제는 이들 간의 통신이 논블로킹 방식으로 이루어지도록 하고 예측 가능한 지연 시간을 보장하는 것입니다. 이는 고성능 네트워크 프로토콜을 설계할 때와 동일한 원칙, 즉 통신 오버헤드를 최소화하고 ‘발신 후 망각(fire-and-forget)’ 패턴을 사용하는 것과 일맥상통합니다.4 따라서 로깅 문제를 단순히 ‘파일에 쓰는 행위’로 볼 것이 아니라, ‘고속의 인메모리 데이터 버스를 설계하는 문제’로 재정의할 필요가 있습니다.

동기식 로깅의 블로킹 문제를 해결하기 위한 가장 근본적인 접근법은 로그 생성과 로그 기록 과정을 분리하는 비동기(asynchronous) 아키텍처를 도입하는 것입니다. 이 아키텍처는 애플리케이션의 핵심 스레드가 I/O 작업의 완료를 기다리지 않도록 하여 시스템의 응답성과 처리량을 극대화합니다.

비동기 로깅 아키텍처는 전형적인 생산자-소비자(Producer-Consumer) 패턴을 따릅니다. 이 패턴은 작업을 생성하는 주체와 처리하는 주체를 분리하여 시스템의 결합도를 낮추고 병렬성을 높이는 데 사용됩니다.

애플리케이션 스레드(생산자)는 로그 이벤트를 생성한 후, 이를 즉시 디스크에 쓰는 대신 메모리상의 버퍼에 넣고 즉시 자신의 원래 작업으로 복귀합니다. 별도의 로거 스레드(소비자)는 이 버퍼를 주기적으로 확인하여 쌓여있는 로그 이벤트들을 가져다가 실제 I/O 작업을 수행합니다.

비동기 아키텍처는 실시간 로깅에 다음과 같은 명백한 이점을 제공합니다.

그러나 비동기 아키텍처는 기존의 문제를 해결하는 동시에 새로운 기술적 과제들을 제시합니다.

비동기 로깅은 I/O가 느리다는 근본적인 문제를 해결하는 것이 아니라, 그 문제를 민감한 애플리케이션 스레드에서 덜 민감한 백그라운드 스레드로 ‘전가’하는 것에 가깝습니다. 만약 로그 생성 속도가 I/O 처리 속도를 지속적으로 초과한다면, 시스템은 결국 버퍼로 사용되는 큐가 무한정 커져 OutOfMemoryError와 같은 메모리 고갈로 인해 실패하게 될 것입니다.11 따라서 비동기 모델은 순간적인 트래픽 폭증에 대한 완충 장치일 뿐, 지속적인 속도 불균형에 대한 해결책은 아닙니다.12 이는 견고한 로깅 아키텍처가 단순히 생산자 측면(logger.log() 호출을 빠르게 만드는 것)에만 집중해서는 안 되며, 소비자 측면(I/O 영속화)의 최적화와 버퍼의 압력(back-pressure)에 대한 명확한 처리 전략(블로킹, 로그 버리기, 버퍼 크기 조절 등)을 반드시 함께 고려해야 함을 시사합니다.

비동기 로깅 아키텍처에서 새로운 성능 병목으로 떠오른 스레드 간 통신 문제를 해결하기 위해서는, 통신의 기본 개념을 명확히 이해하고 잠금(lock)의 한계를 극복하는 고성용 자료 구조를 채택해야 합니다.

고성능 통신 아키텍처를 이해하기 위해, 종종 혼용되는 네 가지 용어를 명확히 구분할 필요가 있습니다. 이들의 차이를 이해하는 것은 후속 아키텍처의 미묘한 차이를 파악하는 데 필수적입니다.

결론적으로, 비동기 로깅은 애플리케이션 관점에서 본질적으로 논블로킹입니다. 우리의 목표는 이 비동기 통신을 뒷받침하는 내부 자료 구조 역시 생산자 스레드에 대해 논블로킹(또는 최소한의 블로킹)으로 설계하는 것입니다.

전통적인 동시성 큐(concurrent queue)는 여러 스레드가 공유 데이터에 안전하게 접근하도록 보장하기 위해 락(lock)이나 뮤텍스(mutex)를 사용합니다. 하지만 높은 경합(contention) 상황, 즉 다수의 스레드가 동시에 로그를 기록하려 할 때, 락을 획득하고 해제하는 과정 자체가 상당한 오버헤드를 유발합니다. 스레드가 락을 기다리는 동안 운영체제에 의해 스케줄링에서 제외될 수 있으며, 이는 예측 불가능한 지연을 초래하여 저지연 설계의 목적을 무력화시킵니다.18

이 문제를 해결하기 위해 잠금 없는(lock-free) 자료 구조가 등장했습니다. 이 자료 구조들은 락 대신, 하드웨어 수준에서 제공하는 원자적 연산(atomic operation), 예를 들어 ‘비교 후 교환(Compare-And-Swap, CAS)’ 같은 명령어를 사용하여 동시 접근을 관리합니다.9 잠금 없는 알고리즘은 평균적인 경우의 성능을 희생하는 대신, 최악의 경우의 성능을 크게 향상시키고 시스템 전체의 진행을 보장(forward progress guarantee)합니다. 즉, 한 스레드가 지연되더라도 다른 스레드의 실행을 방해하지 않습니다.20

잠금 없는 로깅 구현의 핵심에는 링 버퍼(또는 원형 버퍼, circular buffer)가 있습니다.

실세계 최고 수준의 구현 사례로 Java 로깅 프레임워크인 Log4j2의 AsyncLogger를 분석할 수 있습니다. 이 로거는 LMAX Disruptor라는 고성능 MPSC(Multi-Producer Single-Consumer) 큐를 기반으로 설계되었습니다.12

LMAX Disruptor의 등장은 단순한 ‘더 빠른 큐’의 개발을 넘어, 스레드 간 통신에 대한 패러다임의 전환을 의미합니다. 이는 여러 생산자가 공유된 순서 있는 데이터 구조(링 버퍼)를 통해 소비자에게 이벤트를 브로드캐스팅하는 메커니즘으로 이해해야 합니다. 핵심은 데이터 요소 자체를 관리하는 것이 아니라, 순번의 흐름을 제어하는 데 있습니다. 생산자는 순번을 예약하고, 데이터를 쓰고, 순번을 발행합니다. 소비자는 단순히 아이템을 기다리는 것이 아니라 특정 순번이 가용해지기를 기다립니다. 이 구조는 소비자가 한 번의 작업으로 최신 가용 순번까지의 모든 이벤트를 일괄 처리할 수 있게 하여 매우 효율적인 배칭을 가능하게 합니다. 이는 마치 여러 장치가 메모리에 데이터를 쓰고 컨트롤러가 이를 읽어가는 하드웨어 버스의 동작 방식과 유사하며, 시퀀서는 버스 중재자(arbiter) 역할을 합니다. 이러한 설계상의 정교함이 Log4j 1.x의 AsyncAppender에서 사용된 ArrayBlockingQueue와 같은 전통적인 큐 구현과 Log4j2의 AsyncLogger 간의 압도적인 성능 차이를 설명합니다.12

비동기 아키텍처와 잠금 없는 자료 구조를 통해 스레드 간 통신 병목을 해결했다면, 이제 성능의 마지막 관문은 소비자 스레드가 수행하는 실제 I/O 작업의 최적화입니다. 로그 데이터를 얼마나 효율적으로 포맷하고 디스크에 쓰는지가 전체 로깅 시스템의 최종 처리량을 결정합니다.

전통적인 텍스트 기반 로깅은 소비자 스레드에서 두 가지 비용이 큰 연산을 수행합니다.

  1. 포맷팅 (Formatting): 정수, 부동소수점 수, 객체 등 다양한 데이터 타입을 사람이 읽을 수 있는 문자열로 변환하는 과정입니다. 이 과정은 상당한 CPU 자원을 소모합니다.
  2. I/O 볼륨: 텍스트 표현은 종종 매우 장황합니다. 예를 들어, 숫자 1234567890은 텍스트로는 10바이트를 차지하지만, 32비트 정수(integer)로는 단 4바이트면 충분합니다.26 더 많은 데이터를 디스크에 써야 하므로 I/O 시간이 길어집니다.

이러한 비효율을 해결하기 위해 구조화된 바이너리 로깅(structured binary logging) 기법이 제안되었습니다.

I/O 성능을 극대화하기 위한 또 다른 기법으로 메모리 매핑 파일(mmap)이 고려될 수 있습니다.

지금까지 논의된 기술들은 애플리케이션이 스스로의 상태를 기록하는 ‘애플리케이션 중심’의 로깅 방식이었습니다. 그러나 때로는 문제의 근본 원인이 애플리케이션과 운영체제(OS) 간의 상호작용에 있을 수 있습니다. 이러한 경우, 완전히 다른 패러다임의 접근법, 즉 시스템 수준의 트레이싱(tracing)이 필요합니다.

애플리케이션이 자신이 중요하다고 생각하는 것을 기록하는 대신, 시스템 수준의 트레이서를 사용하여 실제로 무슨 일이 일어나고 있는지를 관찰하는 접근법이 있습니다. LTTng(Linux Trace Toolkit: next generation)는 리눅스 커널과 사용자 공간 애플리케이션의 이벤트를 상호 연관시켜 추적할 수 있는 오픈소스 프레임워크입니다.35 LTTng는 개별 컴포넌트가 아닌, 시스템 전체에 대한 통합된 시각을 제공합니다.37

LTTng는 프로덕션 시스템에서도 최소한의 오버헤드로 동작하도록 설계되었습니다. 이러한 성능은 다음과 같은 핵심 아키텍처 요소들 덕분입니다.

성능 문제나 장애의 근본 원인이 애플리케이션과 OS의 상호작용에 있다고 의심될 때, LTTng는 전통적인 애플리케이션 로거보다 월등한 선택지가 됩니다.

지금까지 분석한 다양한 고성능 로깅 기술들은 각각의 장단점과 적합한 사용 사례를 가집니다. 시스템 아키텍트는 주어진 요구사항에 맞춰 최적의 기술 조합을 선택해야 합니다. 이 장에서는 기술들을 종합적으로 비교하고, 특정 사용 사례에 맞는 아키텍처 청사진을 제시합니다.

아래 표는 본 보고서에서 분석한 핵심 로깅 기술들을 실시간 시스템 설계 시 중요하게 고려되는 지표에 따라 비교한 것입니다. 이 표는 복잡한 분석 내용을 하나의 실행 가능한 의사결정 도구로 요약하여, 아키텍트가 특정 제약 조건에 맞는 기술을 신속하게 식별할 수 있도록 돕습니다.

기술 호출 지점 지연 시간 예측 가능성(지터) 최대 처리량 CPU 오버헤드 구현 복잡도 충돌 시 데이터 유실 위험 주요 사용 사례
동기식 로깅 (fwrite) 밀리초(ms) 단위 높음 (예측 불가능) 낮음 높음 (애플리케이션 스레드) 매우 낮음 없음 실시간 시스템에 부적합
비동기 (표준 블로킹 큐) 마이크로초(µs) 단위 중간 중간 낮음 (애플리케이션 스레드) 낮음 높음 (버퍼 내 데이터) 일반적인 비동기 로깅
비동기 (LMAX Disruptor) 나노초(ns) 단위 매우 낮음 매우 높음 매우 낮음 (애플리케이션 스레드) 높음 (라이브러리 사용 시 추상화됨) 높음 (버퍼 내 데이터) 연성 실시간, 고성능 서비스
비동기 (커스텀 MPSC 링 버퍼) 나노초(ns) 단위 매우 낮음 매우 높음 매우 낮음 (애플리케이션 스레드) 매우 높음 높음 (완화 가능) 경성 실시간, 초저지연 시스템
I/O 기법: 바이너리 포맷 (I/O 단계에 적용) (I/O 단계에 적용) (I/O 처리량 증가) 낮음 (소비자 스레드) 중간 (기반 기술에 의존) I/O 병목이 심한 시스템
I/O 기법: mmap (I/O 단계에 적용) 높음 (예측 불가능) (상황에 따라 다름) 중간 (페이지 폴트 비용) 중간 중간 (비동기 플러시) 순차 로깅에 부적합
시스템 트레이싱 (LTTng) 나노초(ns) 단위 매우 낮음 매우 높음 매우 낮음 (계측 지점) 매우 높음 낮음 (복구 메커니즘) 시스템 전반의 진단 및 분석

이러한 시스템에서는 극단적인 성능보다는 안정성, 성숙도, 그리고 사용 편의성 간의 균형이 중요합니다.

이러한 시스템에서는 모든 나노초와 메모리 할당이 중요하며, 예측 가능성이 성능보다 우선시됩니다.

비동기 로깅의 가장 큰 약점은 애플리케이션 충돌 시 메모리 버퍼에 남아있던 로그가 유실된다는 점입니다.14 완전한 감사 추적이 요구되는 시스템에서는 이 문제를 반드시 해결해야 합니다.

본 보고서는 단일 호스트 실시간 애플리케이션에서 블로킹 없는 로깅을 달성하기 위한 다양한 기술들을 심층적으로 분석했습니다. 분석을 통해 다음과 같은 핵심 결론을 도출할 수 있습니다.

본 보고서는 아키텍처 원칙들이 강력한 기반을 제공하지만, 최종적인 결정은 반드시 경험적 증거에 기반해야 함을 강조하며 마무리하고자 합니다.

궁극적인 목표는 애플리케이션의 안정성을 저해하지 않으면서 지연 시간과 처리량 목표를 명백히 만족시키는 로깅 전략을 선택하고 튜닝하는 것입니다. 성능을 고려한 로깅은 단순히 코드를 추가하는 행위가 아니라, 시스템의 가장 깊은 곳에서부터 시작되는 신중한 아키텍처 설계의 결과물입니다.

  1. Real-Time Systems Overview and Examples - Intel, accessed July 3, 2025, https://www.intel.com/content/www/us/en/robotics/real-time-systems.html
  2. On Satisfying Timing Constraints in Hard-Real-Time Systems - ResearchGate, accessed July 3, 2025, https://www.researchgate.net/profile/David-Parnas/publication/3187526_On_Satisfying_Timing_Constraints_in_Hard-Real-Time_Systems/links/55956a8908ae793d137b1701/On-Satisfying-Timing-Constraints-in-Hard-Real-Time-Systems.pdf?origin=scientificContributions
  3. Mastering Hard Real-Time Systems - Number Analytics, accessed July 3, 2025, https://www.numberanalytics.com/blog/mastering-hard-real-time-systems
  4. Asynchronous Logging in API Architecture: A Comprehensive Guide by Sujith C Medium, accessed July 3, 2025, https://sujithchenanath.medium.com/asynchronous-logging-in-api-architecture-a-comprehensive-guide-06aaace50591
  5. Syslog logging stops when the logging synchronous command is configured on the console line - Cisco Community, accessed July 3, 2025, https://community.cisco.com/t5/networking-knowledge-base/syslog-logging-stops-when-the-logging-synchronous-command-is/ta-p/3130999
  6. Asynchronous Processing Salesforce Architects, accessed July 3, 2025, https://architect.salesforce.com/decision-guides/async-processing
  7. how to log asynchronously in a heavily multithreaded environment? - Stack Overflow, accessed July 3, 2025, https://stackoverflow.com/questions/14340146/how-to-log-asynchronously-in-a-heavily-multithreaded-environment
  8. C++ Low-Latency Threaded Asynchronous Buffered Stream (intended for logging) – Boost, accessed July 3, 2025, https://stackoverflow.com/questions/20186859/c-low-latency-threaded-asynchronous-buffered-stream-intended-for-logging-b
  9. An asynchronous lock free ring buffer for logging, accessed July 3, 2025, https://steven-giesel.com/blogPost/11f0ded8-7119-4cfc-b7cf-317ff73fb671/an-asynchronous-lock-free-ring-buffer-for-logging
  10. How to buffer and write to disk a low latency input with C - Stack Overflow, accessed July 3, 2025, https://stackoverflow.com/questions/20284762/how-to-buffer-and-write-to-disk-a-low-latency-input-with-c
  11. Logging is blocking? - Google Groups, accessed July 3, 2025, https://groups.google.com/g/vertx/c/9lzzZ5Ns9pk
  12. Log4j 2 Lock-free Asynchronous Loggers for Low-Latency Logging, accessed July 3, 2025, https://logging.apache.org/log4j/2.12.x/manual/async.html
  13. Configuration and performance of the AsyncAppender in Logback framework, accessed July 3, 2025, https://stackoverflow.com/questions/46411704/configuration-and-performance-of-the-asyncappender-in-logback-framework
  14. Configuring Logging - MuleSoft Documentation, accessed July 3, 2025, https://docs.mulesoft.com/mule-runtime/latest/logging-in-mule
  15. Asynchronous Replication and Data Loss Blog - Continuent, accessed July 3, 2025, https://www.continuent.com/resources/blog/asynchronous-replication-and-data-loss
  16. morganstanley/binlog: A high performance C++ log library … - GitHub, accessed July 3, 2025, https://github.com/morganstanley/binlog
  17. asynchronous and non-blocking calls? also between blocking and synchronous - Stack Overflow, accessed July 3, 2025, https://stackoverflow.com/questions/2625493/asynchronous-and-non-blocking-calls-also-between-blocking-and-synchronous
  18. Ring Buffers: High Performance IPC - ScotlandIS, accessed July 3, 2025, https://www.scotlandis.com/blog/ring-buffers-high-performance-ipc/
  19. Improving Performance of a Trading System through Lock-Free Programming - DiVA portal, accessed July 3, 2025, https://www.diva-portal.org/smash/get/diva2:1252867/FULLTEXT01.pdf
  20. Why doesn’t standard offer wait-free SPSC (and lockfree MPMC) queues? : r/cpp - Reddit, accessed July 3, 2025, https://www.reddit.com/r/cpp/comments/10mq7md/why_doesnt_standard_offer_waitfree_spsc_and/
  21. SPSC lock free queue without atomics - c++ - Stack Overflow, accessed July 3, 2025, https://stackoverflow.com/questions/27139260/spsc-lock-free-queue-without-atomics
  22. An Efficient Unbounded Lock-Free Queue for Multi-core Systems - ResearchGate, accessed July 3, 2025, https://www.researchgate.net/publication/236118159_An_Efficient_Unbounded_Lock-Free_Queue_for_Multi-core_Systems
  23. A Lock Free Multi Producer Single Consumer Queue - Round 1 - Psychosomatic, Lobotomy, Saw, accessed July 3, 2025, http://psy-lob-saw.blogspot.com/2013/10/lock-free-mpsc-1.html
  24. Super Fast Circular Ring Buffer Using Virtual Memory trick by Abhinav Agarwal Medium, accessed July 3, 2025, https://abhinavag.medium.com/super-fast-circular-ring-buffer-4d102ef4d4a3
  25. Log4j – Log4j 2 Asynchronous Loggers for Low-Latency Logging …, accessed July 3, 2025, https://logging.apache.org/log4j/2.3.x/manual/async.html
  26. what is the speed differential of binary versus text file i/o? - Stack Overflow, accessed July 3, 2025, https://stackoverflow.com/questions/3476855/what-is-the-speed-differential-of-binary-versus-text-file-i-o
  27. Simple Binary Logging in Java - Sebastian Daschner, accessed July 3, 2025, https://staging-blog.sebastian-daschner.com/entries/simple-binary-logging
  28. Why do most log files use plain text rather than a binary format?, accessed July 3, 2025, https://softwareengineering.stackexchange.com/questions/332757/why-do-most-log-files-use-plain-text-rather-than-a-binary-format
  29. How does memory mapping a file have significant performance increases over the standard I/O system calls?, accessed July 3, 2025, https://unix.stackexchange.com/questions/474926/how-does-memory-mapping-a-file-have-significant-performance-increases-over-the-s
  30. Understanding when and how to use Memory Mapped Files by Abhijit Mondal, accessed July 3, 2025, https://mecha-mind.medium.com/understanding-when-and-how-to-use-memory-mapped-files-b94707df30e9
  31. File Access: Memory-Mapped vs. I/O System Call Performance Baeldung on Linux, accessed July 3, 2025, https://www.baeldung.com/linux/memory-mapped-vs-system-call
  32. When is mmap faster than fread : r/cpp - Reddit, accessed July 3, 2025, https://www.reddit.com/r/cpp/comments/1l89aft/when_is_mmap_faster_than_fread/
  33. mmap() vs. reading blocks - c++ - Stack Overflow, accessed July 3, 2025, https://stackoverflow.com/questions/45972/mmap-vs-reading-blocks
  34. c++ - mmap for writing sequential log file for speed? - Stack Overflow, accessed July 3, 2025, https://stackoverflow.com/questions/35891525/mmap-for-writing-sequential-log-file-for-speed
  35. LTTng - Wikipedia, accessed July 3, 2025, https://en.wikipedia.org/wiki/LTTng
  36. LTTng: an open source tracing framework for Linux, accessed July 3, 2025, https://lttng.org/
  37. Features - LTTng, accessed July 3, 2025, https://lttng.org/features/
  38. Combined Tracing of the Kernel and Applications with LTTng, accessed July 3, 2025, https://www.kernel.org/doc/ols/2009/ols2009-pages-87-94.pdf
  39. gabime/spdlog: Fast C++ logging library. - GitHub, accessed July 3, 2025, https://github.com/gabime/spdlog
  40. accessed January 1, 1970, https.github.com/gabime/spdlog
  41. moneytech/RingBuffer: Circular buffer library designed for ultra-low-latency Java applications - GitHub, accessed July 3, 2025, https://github.com/moneytech/RingBuffer
  42. First official version of spdlog, a super fast C++ logging library, released : r/cpp - Reddit, accessed July 3, 2025, https://www.reddit.com/r/cpp/comments/4vtyq2/first_official_version_of_spdlog_a_super_fast_c/