21.10.1. `perf_counter` API를 활용한 마이크로(Micro) 단위 지연 시간 측정

21.10.1. perf_counter API를 활용한 마이크로(Micro) 단위 지연 시간 측정

하드 리얼타임(Hard Real-time) 운영체제인 NuttX 위에서 돌아가는 비행 제어 루프(Run())는 보통 20ms(초당 50번) 주기로 쪼개져 돌아간다.
내가 짠 PayloadAutoDrop 모듈의 루프 한 바퀴가 도는 데 20ms를 초과해 버리면(Deadline Miss), 이 모듈은 다음 스케줄을 갉아먹으며 시스템 전체의 타이밍 톱니바퀴를 어그러뜨리기 시작한다.

따라서 내 모듈 탓에 전체 시스템 속도가 느려지지 않는다는 것을 증명하려면, 루프 한 바퀴의 **정확한 실행 시간(Execution Time)**을 뽑아내야 한다.
초보자들은 흔히 루프 앞뒤에 hrt_absolute_time()을 두 번 호출해서 그 차이를 빼서 디버깅 스크린에 PX4_INFO로 띄워보는 끔찍한 짓을 저지른다. 측정 행위 자체가 I/O 부하를 일으켜 대상의 본래 시간을 왜곡시켜 버리는 ’관찰자 효과(Observer Effect)’를 발생시키기 때문이다.

PX4 코어 개발자들은 이 문제를 근본적으로 해결하기 위해 측정 부하(Overhead)가 나노초(ns) 수준에 불과한 영점 조준된 스니퍼(Sniper) 타이머, perf_counter API를 시스템 내부에 박아 두었다.

1. perf_counter의 세 가지 측정 본능

이 초정밀 성능 카운터 시스템은 크게 3가지 형태의 측정 도구를 제공한다.

  1. PC_ELAPSED (소요 시간 측정): 내가 지정한 코드 블록(A 지점부터 B 지점까지)을 헤쳐나가는 데 걸린 ’물리적 시간(Time Elapsed)’을 마이크로초(us) 단위로 정확히 재서 누적해 준다.
  2. PC_COUNT (횟수 집계): 특정 에러 블록(예: uORB 메시지 충돌 발생) 안에 몇 번이나 진입했는지 극도로 적은 부하로 단순히 횟수만 카운팅한다.
  3. PC_INTERVAL (실행 간격 측정): 내 루프가 정말로 20ms마다 정확히 호출되고 있는지, 루프 진입점과 다음 진입점 사이의 시간(Interval) 간격을 재서 스케줄러의 타당성을 검증해 준다.

우리의 최대 관심사는 단연코 내 FSM 루틴이 얼마나 빨리 끝나는지를 묻는 1번, PC_ELAPSED 다.
PC_ELAPSED 카운터 객체를 C++ 클래스에 어떻게 박아 넣고, Run() 함수 앞뒤를 어떻게 영리하게 감싸서 타이밍을 채집할 수 있는지 그 실전 코딩 배치를 21.10.1.1장에서 즉시 적용해 보자.