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:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user