feat(profiler_builtin): support nanosecond accuracy (#7415)

Signed-off-by: pengyiqiang <pengyiqiang@xiaomi.com>
Co-authored-by: pengyiqiang <pengyiqiang@xiaomi.com>
This commit is contained in:
VIFEX
2024-12-06 09:41:15 +08:00
committed by GitHub
parent 945064f6ea
commit 58990cdb5b
5 changed files with 38 additions and 25 deletions

View File

@@ -45,12 +45,13 @@ To enable the profiler, set :c:macro:`LV_USE_PROFILER` in ``lv_conf.h`` and conf
#include <sys/syscall.h> #include <sys/syscall.h>
#include <sys/types.h> #include <sys/types.h>
#include <time.h> #include <time.h>
#include <unistd.h>
static uint32_t my_get_tick_us_cb(void) static uint64_t my_get_tick_us_cb(void)
{ {
struct timespec ts; struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts); clock_gettime(CLOCK_MONOTONIC, &ts);
return ts.tv_sec * 1000000 + ts.tv_nsec / 1000; return ts.tv_sec * 1000000000 + ts.tv_nsec;
} }
static int my_get_tid_cb(void) static int my_get_tid_cb(void)
@@ -69,7 +70,7 @@ To enable the profiler, set :c:macro:`LV_USE_PROFILER` in ``lv_conf.h`` and conf
{ {
lv_profiler_builtin_config_t config; lv_profiler_builtin_config_t config;
lv_profiler_builtin_config_init(&config); lv_profiler_builtin_config_init(&config);
config.tick_per_sec = 1000000; /* One second is equal to 1000000 microseconds */ config.tick_per_sec = 1000000000; /* One second is equal to 1000000000 nanoseconds */
config.tick_get_cb = my_get_tick_us_cb; config.tick_get_cb = my_get_tick_us_cb;
config.tid_get_cb = my_get_tid_cb; config.tid_get_cb = my_get_tid_cb;
config.cpu_get_cb = my_get_cpu_cb; config.cpu_get_cb = my_get_cpu_cb;
@@ -80,12 +81,18 @@ To enable the profiler, set :c:macro:`LV_USE_PROFILER` in ``lv_conf.h`` and conf
.. code-block:: c .. code-block:: c
static uint64_t my_get_tick_us_cb(void)
{
/* Use the microsecond time stamp provided by Arduino */
return micros();
}
void my_profiler_init(void) void my_profiler_init(void)
{ {
lv_profiler_builtin_config_t config; lv_profiler_builtin_config_t config;
lv_profiler_builtin_config_init(&config); lv_profiler_builtin_config_init(&config);
config.tick_per_sec = 1000000; /* One second is equal to 1000000 microseconds */ config.tick_per_sec = 1000000; /* One second is equal to 1000000 microseconds */
config.tick_get_cb = micros; /* Use the microsecond time stamp provided by Arduino */ config.tick_get_cb = my_get_tick_us_cb;
lv_profiler_builtin_init(&config); lv_profiler_builtin_init(&config);
} }

View File

@@ -19,7 +19,7 @@
* DEFINES * DEFINES
*********************/ *********************/
#define TICK_TO_USEC(tick) ((tick) / cpu_freq) #define TICK_TO_NSEC(tick) ((tick) * 1000 / cpu_freq)
/********************** /**********************
* TYPEDEFS * TYPEDEFS
@@ -35,7 +35,7 @@ static uint32_t cpu_freq = 0; /* MHz */
* STATIC VARIABLES * STATIC VARIABLES
**********************/ **********************/
static uint32_t tick_get_cb(void); static uint64_t tick_get_cb(void);
static void flush_cb(const char * buf); static void flush_cb(const char * buf);
/********************** /**********************
@@ -57,7 +57,7 @@ void lv_nuttx_profiler_init(void)
lv_profiler_builtin_config_t config; lv_profiler_builtin_config_t config;
lv_profiler_builtin_config_init(&config); lv_profiler_builtin_config_init(&config);
config.tick_per_sec = 1000000; /* 1 sec = 1000000 usec */ config.tick_per_sec = 1000000000; /* 1 sec = 1000000000 nsec */
config.tick_get_cb = tick_get_cb; config.tick_get_cb = tick_get_cb;
config.flush_cb = flush_cb; config.flush_cb = flush_cb;
lv_profiler_builtin_init(&config); lv_profiler_builtin_init(&config);
@@ -67,10 +67,10 @@ void lv_nuttx_profiler_init(void)
* STATIC FUNCTIONS * STATIC FUNCTIONS
**********************/ **********************/
static uint32_t tick_get_cb(void) static uint64_t tick_get_cb(void)
{ {
static uint32_t prev_tick = 0; static uint32_t prev_tick = 0;
static uint32_t cur_tick_us = 0; static uint64_t cur_tick_ns = 0;
uint32_t act_time = up_perf_gettime(); uint32_t act_time = up_perf_gettime();
uint32_t elaps; uint32_t elaps;
@@ -83,9 +83,9 @@ static uint32_t tick_get_cb(void)
elaps += act_time; elaps += act_time;
} }
cur_tick_us += TICK_TO_USEC(elaps); cur_tick_ns += TICK_TO_NSEC(elaps);
prev_tick = act_time; prev_tick = act_time;
return cur_tick_us; return cur_tick_ns;
} }
static void flush_cb(const char * buf) static void flush_cb(const char * buf)

View File

@@ -20,7 +20,7 @@
#define profiler_ctx LV_GLOBAL_DEFAULT()->profiler_context #define profiler_ctx LV_GLOBAL_DEFAULT()->profiler_context
#define LV_PROFILER_STR_MAX_LEN 128 #define LV_PROFILER_STR_MAX_LEN 128
#define LV_PROFILER_TICK_PER_SEC_MAX 1000000 #define LV_PROFILER_TICK_PER_SEC_MAX 1000000000 /* Maximum accuracy: 1 nanosecond */
#if LV_USE_OS #if LV_USE_OS
#define LV_PROFILER_MULTEX_INIT lv_mutex_init(&profiler_ctx->mutex) #define LV_PROFILER_MULTEX_INIT lv_mutex_init(&profiler_ctx->mutex)
@@ -42,8 +42,8 @@
* @brief Structure representing a built-in profiler item in LVGL * @brief Structure representing a built-in profiler item in LVGL
*/ */
typedef struct { typedef struct {
uint64_t tick; /**< The tick value of the profiler item */
char tag; /**< The tag of the profiler item */ char tag; /**< The tag of the profiler item */
uint32_t tick; /**< The tick value of the profiler item */
const char * func; /**< A pointer to the function associated with the profiler item */ const char * func; /**< A pointer to the function associated with the profiler item */
#if LV_USE_OS #if LV_USE_OS
int tid; /**< The thread ID of the profiler item */ int tid; /**< The thread ID of the profiler item */
@@ -69,6 +69,7 @@ typedef struct _lv_profiler_builtin_ctx_t {
* STATIC PROTOTYPES * STATIC PROTOTYPES
**********************/ **********************/
static uint64_t default_tick_get_cb(void);
static void default_flush_cb(const char * buf); static void default_flush_cb(const char * buf);
static int default_tid_get_cb(void); static int default_tid_get_cb(void);
static int default_cpu_get_cb(void); static int default_cpu_get_cb(void);
@@ -92,7 +93,7 @@ void lv_profiler_builtin_config_init(lv_profiler_builtin_config_t * config)
lv_memzero(config, sizeof(lv_profiler_builtin_config_t)); lv_memzero(config, sizeof(lv_profiler_builtin_config_t));
config->buf_size = LV_PROFILER_BUILTIN_BUF_SIZE; config->buf_size = LV_PROFILER_BUILTIN_BUF_SIZE;
config->tick_per_sec = 1000; config->tick_per_sec = 1000;
config->tick_get_cb = lv_tick_get; config->tick_get_cb = default_tick_get_cb;
config->flush_cb = default_flush_cb; config->flush_cb = default_flush_cb;
config->tid_get_cb = default_tid_get_cb; config->tid_get_cb = default_tid_get_cb;
config->cpu_get_cb = default_cpu_get_cb; config->cpu_get_cb = default_cpu_get_cb;
@@ -208,6 +209,11 @@ void lv_profiler_builtin_write(const char * func, char tag)
* STATIC FUNCTIONS * STATIC FUNCTIONS
**********************/ **********************/
static uint64_t default_tick_get_cb(void)
{
return lv_tick_get();
}
static void default_flush_cb(const char * buf) static void default_flush_cb(const char * buf)
{ {
LV_LOG("%s", buf); LV_LOG("%s", buf);
@@ -236,22 +242,22 @@ static void flush_no_lock(void)
while(cur < profiler_ctx->cur_index) { while(cur < profiler_ctx->cur_index) {
lv_profiler_builtin_item_t * item = &profiler_ctx->item_arr[cur++]; lv_profiler_builtin_item_t * item = &profiler_ctx->item_arr[cur++];
uint32_t sec = item->tick / tick_per_sec; uint32_t sec = item->tick / tick_per_sec;
uint32_t usec = (item->tick % tick_per_sec) * (LV_PROFILER_TICK_PER_SEC_MAX / tick_per_sec); uint32_t nsec = (item->tick % tick_per_sec) * (LV_PROFILER_TICK_PER_SEC_MAX / tick_per_sec);
#if LV_USE_OS #if LV_USE_OS
lv_snprintf(buf, sizeof(buf), lv_snprintf(buf, sizeof(buf),
" LVGL-%d [%d] %" LV_PRIu32 ".%06" LV_PRIu32 ": tracing_mark_write: %c|1|%s\n", " LVGL-%d [%d] %" LV_PRIu32 ".%09" LV_PRIu32 ": tracing_mark_write: %c|1|%s\n",
item->tid, item->tid,
item->cpu, item->cpu,
sec, sec,
usec, nsec,
item->tag, item->tag,
item->func); item->func);
#else #else
lv_snprintf(buf, sizeof(buf), lv_snprintf(buf, sizeof(buf),
" LVGL-1 [0] %" LV_PRIu32 ".%06" LV_PRIu32 ": tracing_mark_write: %c|1|%s\n", " LVGL-1 [0] %" LV_PRIu32 ".%09" LV_PRIu32 ": tracing_mark_write: %c|1|%s\n",
sec, sec,
usec, nsec,
item->tag, item->tag,
item->func); item->func);
#endif #endif

View File

@@ -32,7 +32,7 @@ extern "C" {
struct _lv_profiler_builtin_config_t { struct _lv_profiler_builtin_config_t {
size_t buf_size; /**< The size of the buffer used for profiling data */ size_t buf_size; /**< The size of the buffer used for profiling data */
uint32_t tick_per_sec; /**< The number of ticks per second */ uint32_t tick_per_sec; /**< The number of ticks per second */
uint32_t (*tick_get_cb)(void); /**< Callback function to get the current tick count */ uint64_t (*tick_get_cb)(void); /**< Callback function to get the current tick count */
void (*flush_cb)(const char * buf); /**< Callback function to flush the profiling data */ void (*flush_cb)(const char * buf); /**< Callback function to flush the profiling data */
int (*tid_get_cb)(void); /**< Callback function to get the current thread ID */ int (*tid_get_cb)(void); /**< Callback function to get the current thread ID */
int (*cpu_get_cb)(void); /**< Callback function to get the current CPU */ int (*cpu_get_cb)(void); /**< Callback function to get the current CPU */

View File

@@ -12,7 +12,7 @@ static uint32_t profiler_tick = 0;
static int output_line = 0; static int output_line = 0;
static char output_buf[OUTPUT_LINE_MAX][OUTPUT_BUF_MAX]; static char output_buf[OUTPUT_LINE_MAX][OUTPUT_BUF_MAX];
static uint32_t get_tick_cb(void) static uint64_t get_tick_cb(void)
{ {
return profiler_tick++; return profiler_tick++;
} }
@@ -64,10 +64,10 @@ void test_profiler_normal(void)
/* check output */ /* check output */
TEST_ASSERT_EQUAL_INT(output_line, 4); TEST_ASSERT_EQUAL_INT(output_line, 4);
TEST_ASSERT_EQUAL_INT(profiler_tick, 4); TEST_ASSERT_EQUAL_INT(profiler_tick, 4);
TEST_ASSERT_EQUAL_STRING(output_buf[0], " LVGL-1 [0] 0.000000: tracing_mark_write: B|1|test_profiler_normal\n"); TEST_ASSERT_EQUAL_STRING(output_buf[0], " LVGL-1 [0] 0.000000000: tracing_mark_write: B|1|test_profiler_normal\n");
TEST_ASSERT_EQUAL_STRING(output_buf[1], " LVGL-1 [0] 1.000000: tracing_mark_write: E|1|test_profiler_normal\n"); TEST_ASSERT_EQUAL_STRING(output_buf[1], " LVGL-1 [0] 1.000000000: tracing_mark_write: E|1|test_profiler_normal\n");
TEST_ASSERT_EQUAL_STRING(output_buf[2], " LVGL-1 [0] 2.000000: tracing_mark_write: B|1|custom_tag\n"); TEST_ASSERT_EQUAL_STRING(output_buf[2], " LVGL-1 [0] 2.000000000: tracing_mark_write: B|1|custom_tag\n");
TEST_ASSERT_EQUAL_STRING(output_buf[3], " LVGL-1 [0] 3.000000: tracing_mark_write: E|1|custom_tag\n"); TEST_ASSERT_EQUAL_STRING(output_buf[3], " LVGL-1 [0] 3.000000000: tracing_mark_write: E|1|custom_tag\n");
} }
void test_profiler_disable(void) void test_profiler_disable(void)