LVGL 시뮬레이터에서 Perfetto로 성능 분석하기

LVGL PC 시뮬레이터에는 Perfetto 기반의 프로파일러가 붙어 있어서, 하드웨어 없이도 주요 이벤트의 지연과 렌더링 상태를 타임라인으로 시각화할 수 있습니다. 시뮬레이터를 빌드하고 profiler.systrace를 만들어 Perfetto에서 확인하는 과정을 차근차근 정리합니다.

물론, Perfetto 파일로 바로 캡쳐는 안되고, 퍼페토 형식의 트레이스 로그를 먼저 출력하고, 그 로그를 기반으로 파이썬 스크립트로 퍼페토 트레이스 파일로 변환해야 합니다. 한번 더 과정이 있긴 하지만, 시각화하여 성능을 분석할 수 있습니다.

1. 퍼페토 시각화 과정

기본적으로 퍼페토 트레이싱 로그가 출력되지 않습니다.

아래와 같은 과정을 거칩니다.

  1. 먼저 퍼페토 트레이싱 정보를 로그에 출력하도록 만들고
  2. 출력된 텍스트를 소스에 있는 파이썬 스크립트로 Perfetto trace 파일로 변환
  3. 변환된 파일을 perfetto 웹페이지에서 로딩하여 확인

2. 필요한 설정 (Perfetto 로그 출력)

  • lv_conf.h에서 LV_USE_PROFILER, LV_USE_PROFILER_BUILTIN, LV_USE_PROFILER_BUILTIN_POSIX를 1로 켜고 버퍼 크기를 충분히 키우세요. 그럼 LVGL이 내부에서 systrace 포맷 로그를 찍습니다.
  • src/main.c에는 lv_profiler_builtin_config_t를 포함하여 고해상도 타이머(clock_gettime 또는 QueryPerformanceCounter)와 기록을 모을 콜백을 초기화합니다. init_profiler()lv_init() 직후 호출하면 안정적입니다.

아래는 lv_conf.hsrc/main.c에 수정한 코드입니다.

diff --git a/lv_conf.h b/lv_conf.h
@@
-#define LV_USE_PROFILER 0
+#define LV_USE_PROFILER 1
@@
-#define LV_PROFILER_BUILTIN_BUF_SIZE (16 * 1024)
-#define LV_USE_PROFILER_BUILTIN_POSIX 0
+#define LV_PROFILER_BUILTIN_BUF_SIZE (32 * 1024)
+#define LV_USE_PROFILER_BUILTIN_POSIX 1
diff --git a/src/main.c b/src/main.c
@@
-#include "lvgl/demos/lv_demos.h"
+#include "lvgl/demos/lv_demos.h"
+#if LV_USE_PROFILER
+#include LV_PROFILER_INCLUDE
+#if LV_USE_PROFILER_BUILTIN
+#include "lvgl/src/misc/lv_profiler_builtin_private.h"
+#endif
+#endif
@@
-  lv_init();
+  lv_init();
+#if LV_USE_PROFILER
+  init_profiler();
+#endif
@@
+#if LV_USE_PROFILER
+static void init_profiler(void)
+{
+  lv_profiler_builtin_config_t cfg;
+  lv_profiler_builtin_config_init(&cfg);
+  cfg.tick_per_sec = 1000000;
+  cfg.tick_get_cb = profiler_tick_cb;
+  cfg.flush_cb = profiler_flush_cb;
+  lv_profiler_builtin_init(&cfg);
+  atexit(close_profiler_output);
+}
+#endif

3. 시뮬레이터 빌드

코드를 수정했으면 빌드를 합니다.

cmake -S . -B build
cmake --build build

build/main 바이너리가 생성되는지 확인하고, 오류가 나면 lv_conf.hsrc 쪽 include 경로를 점검합니다.

4. UI를 실행하여 로그 만들기

에뮬레이터를 실행하고, UI를 동작시키면 트레이싱 로그가 지속적으로 저장됩니다.

./bin/main

테스트를 마치고 Ctrl+C로 종료하세요. 그러면 프로젝트 루트에 profiler.systrace 파일이 생깁니다.

5. systrace → Perfetto 전처리

이 스크립트는 프로젝트에 있는건데, LVGL 로그에서 Perfetto가 이해하는 .systrace 형식으로 변경합니다.

python3 lvgl/scripts/trace_filter.py profiler.systrace perfetto.systrace

6. Perfetto에서 분석하기

  1. https://ui.perfetto.dev에 접속
  2. “Import trace”로 perfetto.systrace 업로드
  3. 성능 병목 구간 확인 및 분석

7. 팁

  • LV_PROFILER_BEGIN_TAG("Tag")/LV_PROFILER_END_TAG로 직접 태그를 찍으면 원하는 함수만 따로 보기가 쉽습니다.
  • 여러 테스트를 구분하려면 profiler_flush_cb()에서 날짜/시간을 붙인 파일명으로 기록하세요.
  • LV_LOG()과 함께 출력하면 콘솔 로그와 타임라인을 비교하며 문제를 추적할 수 있습니다.

8. 퍼페토 로딩 화면

시뮬레이터 실행

8. 퍼페토 변환 전, 'profiler.systrace' 파일

'profiler.systrace' 파일은 이런식으로 저장됩니다.

그리고, 스크립트로 perfetto가 이해하는 systrace로 변환합니다.

# tracer: nop
#
   LVGL-1 [0] 8160.090859000: tracing_mark_write: B|1|EVENT_STYLE_CHANGED
   LVGL-1 [0] 8160.090861000: tracing_mark_write: E|1|EVENT_STYLE_CHANGED
   LVGL-1 [0] 8160.090864000: tracing_mark_write: B|1|lv_obj_refresh_ext_draw_size
   LVGL-1 [0] 8160.090866000: tracing_mark_write: B|1|EVENT_REFR_EXT_DRAW_SIZE
   LVGL-1 [0] 8160.090867000: tracing_mark_write: B|1|lv_obj_calculate_ext_draw_size
   LVGL-1 [0] 8160.090870000: tracing_mark_write: E|1|lv_obj_calculate_ext_draw_size
   LVGL-1 [0] 8160.090871000: tracing_mark_write: E|1|EVENT_REFR_EXT_DRAW_SIZE