feat(profiler): add performance profiler hook (#4211)

Signed-off-by: pengyiqiang <pengyiqiang@xiaomi.com>
Co-authored-by: pengyiqiang <pengyiqiang@xiaomi.com>
This commit is contained in:
_VIFEXTech
2023-05-11 17:10:47 +08:00
committed by GitHub
parent 3e3daf0f04
commit 540c028d60
18 changed files with 169 additions and 4 deletions

View File

@@ -1009,6 +1009,13 @@ menu "LVGL configuration"
bool "Enable Monkey test" bool "Enable Monkey test"
default n default n
config LV_USE_PROFILER
bool "Run-time performance profiler."
config LV_PROFILER_INCLUDE
string "Header to include for the profiler"
depends on LV_USE_PROFILER
default "profiler.h"
config LV_USE_GRIDNAV config LV_USE_GRIDNAV
bool "Enable grid navigation" bool "Enable grid navigation"
default n default n

View File

@@ -16,4 +16,5 @@ Porting
sleep sleep
os os
log log
profiler
draw draw

42
docs/porting/profiler.rst Normal file
View File

@@ -0,0 +1,42 @@
.. _profiler:
========
Profiler
========
As the complexity of the application increases, performance issues
such as low FPS and frequent cache misses causing lag may arise.
LVGL has internally set up some hooks for performance measurement
to help developers analyze and locate performance issues.
Porting
*******
To enable profiler, set :c:macro:`LV_USE_PROFILER` in ``lv_conf.h`` and configure the following options:
- :c:macro:`LV_PROFILER_INCLUDE`: Provides a header file for the performance measurement function.
- :c:macro:`LV_PROFILER_BEGIN`: Performance measurement start point function.
- :c:macro:`LV_PROFILER_END`: Performance measurement end point function.
Example
*******
The following is an example of output performance measurements using LVGL logging systems:
Configure ``lv_conf.h``:
.. code:: c
#define LV_USE_PROFILER 1
#define LV_PROFILER_INCLUDE "lvgl/src/hal/lv_hal_tick.h"
#define LV_PROFILER_BEGIN uint32_t profiler_start = lv_tick_get()
#define LV_PROFILER_END LV_LOG_USER("cost %" LV_PRIu32 "ms", lv_tick_elaps(profiler_start))
Users can add the measured functions themselves:
.. code:: c
LV_PROFILER_BEGIN;
my_func();
LV_PROFILER_END;

View File

@@ -700,6 +700,12 @@
/*1: Enable system monitor component*/ /*1: Enable system monitor component*/
#define LV_USE_SYSMON 0 #define LV_USE_SYSMON 0
/*1: Enable the run-time performance profiler*/
#define LV_USE_PROFILER 0
#define LV_PROFILER_INCLUDE <stdint.h>
#define LV_PROFILER_BEGIN
#define LV_PROFILER_END
/*1: Enable Monkey test*/ /*1: Enable Monkey test*/
#define LV_USE_MONKEY 0 #define LV_USE_MONKEY 0

View File

@@ -14,6 +14,7 @@
#include "../misc/lv_timer.h" #include "../misc/lv_timer.h"
#include "../misc/lv_math.h" #include "../misc/lv_math.h"
#include "../misc/lv_gc.h" #include "../misc/lv_gc.h"
#include "../misc/lv_profiler.h"
#include "../draw/lv_draw.h" #include "../draw/lv_draw.h"
#include "../font/lv_font_fmt_txt.h" #include "../font/lv_font_fmt_txt.h"
@@ -231,6 +232,7 @@ lv_disp_t * _lv_refr_get_disp_refreshing(void)
*/ */
void _lv_disp_refr_timer(lv_timer_t * tmr) void _lv_disp_refr_timer(lv_timer_t * tmr)
{ {
LV_PROFILER_BEGIN;
REFR_TRACE("begin"); REFR_TRACE("begin");
uint32_t start = lv_tick_get(); uint32_t start = lv_tick_get();
@@ -341,6 +343,7 @@ refr_finish:
lv_disp_send_event(disp_refr, LV_EVENT_REFR_FINISH, NULL); lv_disp_send_event(disp_refr, LV_EVENT_REFR_FINISH, NULL);
REFR_TRACE("finished"); REFR_TRACE("finished");
LV_PROFILER_END;
} }
/********************** /**********************
@@ -390,6 +393,7 @@ static void lv_refr_join_area(void)
static void refr_invalid_areas(void) static void refr_invalid_areas(void)
{ {
if(disp_refr->inv_p == 0) return; if(disp_refr->inv_p == 0) return;
LV_PROFILER_BEGIN;
/*Find the last area which will be drawn*/ /*Find the last area which will be drawn*/
int32_t i; int32_t i;
@@ -419,6 +423,7 @@ static void refr_invalid_areas(void)
} }
disp_refr->rendering_in_progress = false; disp_refr->rendering_in_progress = false;
LV_PROFILER_END;
} }
/** /**

View File

@@ -44,7 +44,9 @@ void lv_draw_init(void)
void lv_draw_wait_for_finish(lv_draw_ctx_t * draw_ctx) void lv_draw_wait_for_finish(lv_draw_ctx_t * draw_ctx)
{ {
LV_PROFILER_BEGIN;
if(draw_ctx->wait_for_finish) draw_ctx->wait_for_finish(draw_ctx); if(draw_ctx->wait_for_finish) draw_ctx->wait_for_finish(draw_ctx);
LV_PROFILER_END;
} }
/********************** /**********************

View File

@@ -17,6 +17,7 @@ extern "C" {
#include "../misc/lv_style.h" #include "../misc/lv_style.h"
#include "../misc/lv_txt.h" #include "../misc/lv_txt.h"
#include "../misc/lv_profiler.h"
#include "lv_img_decoder.h" #include "lv_img_decoder.h"
#include "lv_img_cache.h" #include "lv_img_cache.h"

View File

@@ -48,10 +48,12 @@ void lv_draw_arc(lv_draw_ctx_t * draw_ctx, const lv_draw_arc_dsc_t * dsc, const
if(dsc->width == 0) return; if(dsc->width == 0) return;
if(start_angle == end_angle) return; if(start_angle == end_angle) return;
LV_PROFILER_BEGIN;
draw_ctx->draw_arc(draw_ctx, dsc, center, radius, start_angle, end_angle); draw_ctx->draw_arc(draw_ctx, dsc, center, radius, start_angle, end_angle);
// const lv_draw_backend_t * backend = lv_draw_backend_get(); // const lv_draw_backend_t * backend = lv_draw_backend_get();
// backend->draw_arc(center_x, center_y, radius, start_angle, end_angle, clip_area, dsc); // backend->draw_arc(center_x, center_y, radius, start_angle, end_angle, clip_area, dsc);
LV_PROFILER_END;
} }
void lv_draw_arc_get_area(lv_coord_t x, lv_coord_t y, uint16_t radius, uint16_t start_angle, uint16_t end_angle, void lv_draw_arc_get_area(lv_coord_t x, lv_coord_t y, uint16_t radius, uint16_t start_angle, uint16_t end_angle,

View File

@@ -69,6 +69,7 @@ void lv_draw_img(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, const
if(dsc->opa <= LV_OPA_MIN) return; if(dsc->opa <= LV_OPA_MIN) return;
LV_PROFILER_BEGIN;
lv_res_t res; lv_res_t res;
if(draw_ctx->draw_img) { if(draw_ctx->draw_img) {
res = draw_ctx->draw_img(draw_ctx, dsc, coords, src); res = draw_ctx->draw_img(draw_ctx, dsc, coords, src);
@@ -76,6 +77,7 @@ void lv_draw_img(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc, const
else { else {
res = decode_and_draw(draw_ctx, dsc, coords, src); res = decode_and_draw(draw_ctx, dsc, coords, src);
} }
LV_PROFILER_END;
if(res == LV_RES_INV) { if(res == LV_RES_INV) {
LV_LOG_WARN("Image draw error"); LV_LOG_WARN("Image draw error");
@@ -121,8 +123,9 @@ void lv_draw_img_decoded(lv_draw_ctx_t * draw_ctx, const lv_draw_img_dsc_t * dsc
const uint8_t * map_p, const lv_draw_img_sup_t * sup, lv_color_format_t color_format) const uint8_t * map_p, const lv_draw_img_sup_t * sup, lv_color_format_t color_format)
{ {
if(draw_ctx->draw_img_decoded == NULL) return; if(draw_ctx->draw_img_decoded == NULL) return;
LV_PROFILER_BEGIN;
draw_ctx->draw_img_decoded(draw_ctx, dsc, coords, map_p, sup, color_format); draw_ctx->draw_img_decoded(draw_ctx, dsc, coords, map_p, sup, color_format);
LV_PROFILER_END;
} }
/********************** /**********************

View File

@@ -364,7 +364,9 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_label(lv_draw_ctx_t * draw_ctx, const lv_draw
void lv_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p, void lv_draw_letter(lv_draw_ctx_t * draw_ctx, const lv_draw_label_dsc_t * dsc, const lv_point_t * pos_p,
uint32_t letter) uint32_t letter)
{ {
LV_PROFILER_BEGIN;
draw_ctx->draw_letter(draw_ctx, dsc, pos_p, letter); draw_ctx->draw_letter(draw_ctx, dsc, pos_p, letter);
LV_PROFILER_END;
} }

View File

@@ -45,6 +45,7 @@ lv_draw_layer_ctx_t * lv_draw_layer_create(lv_draw_ctx_t * draw_ctx, const lv_ar
LV_LOG_WARN("Couldn't allocate a new layer context"); LV_LOG_WARN("Couldn't allocate a new layer context");
return NULL; return NULL;
} }
LV_PROFILER_BEGIN;
lv_memzero(layer_ctx, draw_ctx->layer_instance_size); lv_memzero(layer_ctx, draw_ctx->layer_instance_size);
@@ -55,27 +56,33 @@ lv_draw_layer_ctx_t * lv_draw_layer_create(lv_draw_ctx_t * draw_ctx, const lv_ar
layer_ctx->area_full = *layer_area; layer_ctx->area_full = *layer_area;
lv_draw_layer_ctx_t * init_layer_ctx = draw_ctx->layer_init(draw_ctx, layer_ctx, flags); lv_draw_layer_ctx_t * init_layer_ctx = draw_ctx->layer_init(draw_ctx, layer_ctx, flags);
if(NULL == init_layer_ctx) { if(NULL == init_layer_ctx) {
lv_free(layer_ctx); lv_free(layer_ctx);
} }
LV_PROFILER_END;
return init_layer_ctx; return init_layer_ctx;
} }
void lv_draw_layer_adjust(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, void lv_draw_layer_adjust(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx,
lv_draw_layer_flags_t flags) lv_draw_layer_flags_t flags)
{ {
LV_PROFILER_BEGIN;
if(draw_ctx->layer_adjust) draw_ctx->layer_adjust(draw_ctx, layer_ctx, flags); if(draw_ctx->layer_adjust) draw_ctx->layer_adjust(draw_ctx, layer_ctx, flags);
LV_PROFILER_END;
} }
void lv_draw_layer_blend(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx, void lv_draw_layer_blend(struct _lv_draw_ctx_t * draw_ctx, struct _lv_draw_layer_ctx_t * layer_ctx,
lv_draw_img_dsc_t * draw_dsc) lv_draw_img_dsc_t * draw_dsc)
{ {
LV_PROFILER_BEGIN;
if(draw_ctx->layer_blend) draw_ctx->layer_blend(draw_ctx, layer_ctx, draw_dsc); if(draw_ctx->layer_blend) draw_ctx->layer_blend(draw_ctx, layer_ctx, draw_dsc);
LV_PROFILER_END;
} }
void lv_draw_layer_destroy(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx) void lv_draw_layer_destroy(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer_ctx)
{ {
LV_PROFILER_BEGIN;
lv_draw_wait_for_finish(draw_ctx); lv_draw_wait_for_finish(draw_ctx);
draw_ctx->buf = layer_ctx->original.buf; draw_ctx->buf = layer_ctx->original.buf;
draw_ctx->buf_area = layer_ctx->original.buf_area; draw_ctx->buf_area = layer_ctx->original.buf_area;
@@ -84,6 +91,7 @@ void lv_draw_layer_destroy(lv_draw_ctx_t * draw_ctx, lv_draw_layer_ctx_t * layer
if(draw_ctx->layer_destroy) draw_ctx->layer_destroy(draw_ctx, layer_ctx); if(draw_ctx->layer_destroy) draw_ctx->layer_destroy(draw_ctx, layer_ctx);
lv_free(layer_ctx); lv_free(layer_ctx);
LV_PROFILER_END;
} }
/********************** /**********************

View File

@@ -48,7 +48,9 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_line(struct _lv_draw_ctx_t * draw_ctx, const
if(dsc->width == 0) return; if(dsc->width == 0) return;
if(dsc->opa <= LV_OPA_MIN) return; if(dsc->opa <= LV_OPA_MIN) return;
LV_PROFILER_BEGIN;
draw_ctx->draw_line(draw_ctx, dsc, point1, point2); draw_ctx->draw_line(draw_ctx, dsc, point1, point2);
LV_PROFILER_END;
} }
/********************** /**********************

View File

@@ -63,8 +63,9 @@ void lv_draw_rect(lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * dsc, cons
{ {
if(lv_area_get_height(coords) < 1 || lv_area_get_width(coords) < 1) return; if(lv_area_get_height(coords) < 1 || lv_area_get_width(coords) < 1) return;
LV_PROFILER_BEGIN;
draw_ctx->draw_rect(draw_ctx, dsc, coords); draw_ctx->draw_rect(draw_ctx, dsc, coords);
LV_PROFILER_END;
LV_ASSERT_MEM_INTEGRITY(); LV_ASSERT_MEM_INTEGRITY();
} }

View File

@@ -46,7 +46,9 @@ void lv_draw_transform(lv_draw_ctx_t * draw_ctx, const lv_area_t * dest_area, co
return; return;
} }
LV_PROFILER_BEGIN;
draw_ctx->draw_transform(draw_ctx, dest_area, src_buf, src_w, src_h, src_stride, draw_dsc, sup, cf, cbuf, abuf); draw_ctx->draw_transform(draw_ctx, dest_area, src_buf, src_w, src_h, src_stride, draw_dsc, sup, cf, cbuf, abuf);
LV_PROFILER_END;
} }

View File

@@ -38,13 +38,16 @@
void lv_draw_polygon(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t points[], void lv_draw_polygon(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t points[],
uint16_t point_cnt) uint16_t point_cnt)
{ {
LV_PROFILER_BEGIN;
draw_ctx->draw_polygon(draw_ctx, draw_dsc, points, point_cnt); draw_ctx->draw_polygon(draw_ctx, draw_dsc, points, point_cnt);
LV_PROFILER_END;
} }
void lv_draw_triangle(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t points[]) void lv_draw_triangle(struct _lv_draw_ctx_t * draw_ctx, const lv_draw_rect_dsc_t * draw_dsc, const lv_point_t points[])
{ {
LV_PROFILER_BEGIN;
draw_ctx->draw_polygon(draw_ctx, draw_dsc, points, 3); draw_ctx->draw_polygon(draw_ctx, draw_dsc, points, 3);
LV_PROFILER_END;
} }
/********************** /**********************

View File

@@ -2346,6 +2346,36 @@
#endif #endif
#endif #endif
/*1: Enable the run-time performance profiler*/
#ifndef LV_USE_PROFILER
#ifdef CONFIG_LV_USE_PROFILER
#define LV_USE_PROFILER CONFIG_LV_USE_PROFILER
#else
#define LV_USE_PROFILER 0
#endif
#endif
#ifndef LV_PROFILER_INCLUDE
#ifdef CONFIG_LV_PROFILER_INCLUDE
#define LV_PROFILER_INCLUDE CONFIG_LV_PROFILER_INCLUDE
#else
#define LV_PROFILER_INCLUDE <stdint.h>
#endif
#endif
#ifndef LV_PROFILER_BEGIN
#ifdef CONFIG_LV_PROFILER_BEGIN
#define LV_PROFILER_BEGIN CONFIG_LV_PROFILER_BEGIN
#else
#define LV_PROFILER_BEGIN
#endif
#endif
#ifndef LV_PROFILER_END
#ifdef CONFIG_LV_PROFILER_END
#define LV_PROFILER_END CONFIG_LV_PROFILER_END
#else
#define LV_PROFILER_END
#endif
#endif
/*1: Enable Monkey test*/ /*1: Enable Monkey test*/
#ifndef LV_USE_MONKEY #ifndef LV_USE_MONKEY
#ifdef CONFIG_LV_USE_MONKEY #ifdef CONFIG_LV_USE_MONKEY

45
src/misc/lv_profiler.h Normal file
View File

@@ -0,0 +1,45 @@
/**
* @file lv_profiler.h
*
*/
#ifndef LV_PROFILER_H
#define LV_PROFILER_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#include "../lv_conf_internal.h"
#if LV_USE_PROFILER
#include LV_PROFILER_INCLUDE
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**********************
* MACROS
**********************/
#endif /*LV_USE_PROFILER*/
#ifdef __cplusplus
} /*extern "C"*/
#endif
#endif /*LV_PROFILER_H*/

View File

@@ -12,6 +12,7 @@
#include "lv_ll.h" #include "lv_ll.h"
#include "lv_gc.h" #include "lv_gc.h"
#include "lv_printf.h" #include "lv_printf.h"
#include "lv_profiler.h"
/********************* /*********************
* DEFINES * DEFINES
@@ -82,6 +83,7 @@ LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_timer_handler(void)
return 1; return 1;
} }
LV_PROFILER_BEGIN;
static uint32_t idle_period_start = 0; static uint32_t idle_period_start = 0;
static uint32_t busy_time = 0; static uint32_t busy_time = 0;
@@ -143,6 +145,7 @@ LV_ATTRIBUTE_TIMER_HANDLER uint32_t lv_timer_handler(void)
already_running = false; /*Release the mutex*/ already_running = false; /*Release the mutex*/
TIMER_TRACE("finished (%" LV_PRIu32 " ms until the next timer call)", time_till_next); TIMER_TRACE("finished (%" LV_PRIu32 " ms until the next timer call)", time_till_next);
LV_PROFILER_END;
return time_till_next; return time_till_next;
} }