21.10.2. NSH 환경에서의 하드웨어 리소스 및 메모리 릭(Leak) 추적
앞 장에서 다루었던 perf_counter가 내 코드가 ’얼마나 빨리 달리는가’를 재는 스톱워치였다면, 이번 장에서 다룰 내용들은 내 코드가 ’얼마나 많은 밥(RAM)과 공기(CPU)를 축내고 있는가’를 재는 체성분 분석기다.
픽스호크 4(Pixhawk 4)에 탑재된 STM32F7 두뇌는 램(RAM) 용량이 고작 수백 킬로바이트(KB) 남짓에 불과하다. 최신 데스크톱 PC의 램이 32GB(약 3,300만 KB)인 것과 비교하면 먼지 같은 크기다.
여기서 바이트 단위의 메모리 누수(Memory Leak)를 일으키는 짜장면(C++) 코드를 작성해 둔다면 어찌 될까?
비행 시작 10분 만에 전체 시스템의 램이 꽉 차서 OOM(Out of Memory) 스위치가 터지며, 모든 프로펠러 모터가 동시에 꺼지는 참상을 겪게 될 것이다.
PX4의 NSH (NuttShell) 환경은 이런 참극을 미연에 방지하고 병목을 추적하기 위해 리눅스 매니아들에게 친숙한 명령어 삼대장(top, free, work_queue)을 임베디드 코어에 맞춰 이식해 두었다.
1. free: 드론의 총 보유 자산 확인
터미널 커맨드 라인에 free를 덩그러니 치면 픽스호크 배때기에 남은 여유 공간이 숫자로 뜬다.
nsh> free
total used free largest
Mem: 236960 160864 76096 65312
이 로그가 의미하는 바는 이 기체의 총사용 가능한 힙 메모리(Heap)가 236KB인데, 각종 모듈들이 160KB를 쪼개서 가져다 썼고 이제 76KB의 숨구멍이 남았다는 뜻이다.
테스트 비행을 1시간 넘게 켜두면서 주기적으로 free를 쳤을 때, 저 남은 공간(free) 숫자가 서서히 줄어들고 있다면 **100% 당신의 모듈 어딘가에서 메모리 누수(Leak)**가 벌어지고 있다는 사형 선고나 다름없다.
2. top: 데몬들의 잔혹한 서열 매기기
리눅스의 전유물인 top 명령어는 픽스호크 안에서도 똑같이 작동한다.
nsh> top
PID COMMAND CPU(ms) CPU(%) USED/STACK PRIO(BASE) STATE
0 Idle Task 582453 65.462 0/ 0 0 ( 0) READY
26 hpwork 2617 0.467 704/ 1784 192 (192) w:sem
32 logger 19542 3.437 1288/ 3560 250 (250) w:sem
81 ekf2 42189 7.360 3448/ 6600 250 (250) w:sem
104 payload_autodrop 12 0.031 512/ 1200 100 (100) w:sem
...
위 표를 잘 보라. 이것은 현재 픽스호크 안에서 밥그릇 싸움을 벌이고 있는 데몬(Task)들의 처절한 생존 현장이다.
CPU(%): 우리가 새로 깎아 넣은payload_autodrop모듈의 일꾼이 전체 CPU 연산력의 고작 0.031% 만을 쓰면서 착하게 돌아가고 있다 반면, 가장 뚱뚱한 데몬인ekf2는 혼자서 7.3%나 처묵처묵하고 있다.- 만약 내 페이로즈 모듈의 CPU 점유율이 5%를 넘어간다면, 비즈니스 로직 연산 어딘가에 터무니없는 부하가 걸려 있다는 끔찍한 뜻이므로 당장
Run()함수 안의 부하 코드를 주석 처리(분해)하며 원인을 추적해야 한다.
그런데 저 표에서 CPU 보다 파멸적으로 중요한 컬럼이 있다. 바로 USED/STACK 컬럼이다.
과연 내 모듈이 터지기(Stack Overflow) 직전인 시한폭탄 상태일까 아닐까? 21.10.2.1장에서 이 스택 마진(Stack Margin)을 해석하고 CMakeLists.txt로 튜닝하는 목숨을 건 줄타기 공식을 공개한다.