Object create time increase as total object number increases

Hi All,

I’m using the below function to create line object.
However I found out that the process time increase as the total object number increase.

line = lv_line_create(lv_disp_get_scr_act(g_disp[Chan][disp_count[Chan]]),NULL);

For example,
when I first create the line, it takes about 0.024ms to process lv_create_line()
However, when the total object number increase to 180, it takes about 0.087ms to create a line object.

May I know the reason?
Or Could someone guide me how to improve this?

Futhermore, I found out that
lv_obj_set_style_local_line_xxx has the same situation. (process time increase as total object number increase.)

The code block(s) should be formatted like:

void DrawLine(UINT32 Chan, UINT32 X1, UINT32 Y1, UINT32 X2, UINT32 Y2, UINT32 LineWidth, UINT32 Color, UINT32 *LineTotal)
{

    lv_obj_t * line;
    lv_color_t line_color;
    lv_point_t _point[2] = {{(lv_coord_t)X1,(lv_coord_t)Y1},{(lv_coord_t)X2,(lv_coord_t)Y2}};


    line_points[Chan][line_count[Chan]] = _point[0];
    line_points[Chan][line_count[Chan]+1U] = _point[1];
    
    line_color.full = Color;
   
    /* Measure time */
    line = lv_line_create(lv_disp_get_scr_act(g_disp[Chan][disp_count[Chan]]),NULL);
   /* Measure time */

    lv_obj_set_pos(line,0,0);

    lv_obj_add_style(line,LV_LINE_PART_MAIN,&style_line);

    lv_line_set_points(line,&line_points[Chan][line_count[Chan]],2U);

    lv_obj_set_style_local_line_color(line,LV_OBJ_PART_MAIN,LV_STATE_DEFAULT,line_color);

    lv_obj_set_style_local_line_width(line,LV_OBJ_PART_MAIN,LV_STATE_DEFAULT,(lv_coord_t)LineWidth);

    lv_obj_set_style_local_line_opa(line,LV_OBJ_PART_MAIN,LV_STATE_DEFAULT,Color>>24);
   

}

I’ve check further into the source code, and found out that it is void * lv_mem_alloc(size_t size) that takes most of the time.

Since I do not use custome malloc, therefore, the code flow should run below

#if LV_MEM_CUSTOM == 0
    /*Use the built-in allocators*/
    lv_mem_ent_t * e = NULL;

    /* Search for a appropriate entry*/
    do {
        /* Get the next entry*/
        e = ent_get_next(e);

        /*If there is next entry then try to allocate there*/
        if(e != NULL) {
            alloc = ent_alloc(e, size);
        }
        /* End if there is not next entry OR the alloc. is successful*/
    } while(e != NULL && alloc == NULL);

#else

I think it is because object is getting more and more, therefore, it takes more than to find next entry.

May I know is there a good solution to improve this?

Many Thanks for your help.

The heap implementation in v7 is definitely not perfect. If your platform has a better heap allocator, you can try using LV_MEM_CUSTOM and see if it helps performance.

However, even with your figures, it would only take 16ms to create 180 line objects. In my opinion, that’s a very acceptable speed.

Many Thanks for your reply.

I’ve check v8, and it’s heap implementation is different.
I wonder that if I only apply lv_mem.c and its related files (lv_tlsf.c) from v8 to v7, would it be possible?
Is there any side effect?

I observe that v8 changes a lot compared to v7.
It would take much effort to update my code base to v8.

It’d probably be faster to install standalone TLSF and configure it as the custom heap in lv_conf.h.

@embeddedt many thanks for your help.
I use tlsf as custom and it works now.

However, I got some questions.
I use lv_mem_monitor to monitor memory usage.

My LV_MEM_SIZE is 20KB.
After lv_init(), I my free size is
[LVGL|NG]: ###2 Use Prectgange is :[12], free_size:[0x70E8] ###.
Is it normal?

After that I check memory usage before I create a new object.
Then I got below error.

[LVGL|NG]: Use Prectgange is :[71], free_size:[0x2540]
[lv_mem_alloc][Level:[2], Line:[219]]: Couldn’t allocate memory
[lv_mem_realloc][Level:[2], Line:[334]]: Couldn’t allocate memory
[_lv_mem_buf_get][Level:[3], Line:[570]]: _lv_mem_buf_get
[lv_debug_log_error][Level:[3], Line:[127]]: Out of memory, can’t allocate a new buffer (increase your LV_MEM_SIZE/heap size (0x00000000)

However, it seems that I still have 0x2540 free size.
I wonder why the error happen?

The reason why I check memeory usage every time is because I want to prevent out of memory.
Since when there is no enough memory, lvgl will be stuck in while loop. (assertion happen).
However, I want lvgl to ignore the object and keep drawing instead of being stuck there.

Is there better solution for this?

My tlsf.c and tlsf.h is directly copied from source code.

void lv_mem_monitor(lv_mem_monitor_t * mon_p)
{
    /*Init the data*/
    _lv_memset(mon_p, 0, sizeof(lv_mem_monitor_t));
#if LV_MEM_CUSTOM == 0
    ...

#else

    tlsf_walk_pool(tlsf_get_pool(tlsf), lv_mem_walker, mon_p);

    mon_p->total_size = LV_MEM_SIZE;
    mon_p->used_pct = 100 - (100U * mon_p->free_size) / mon_p->total_size;
    if(mon_p->free_size > 0) {
        mon_p->frag_pct = mon_p->free_biggest_size * 100U / mon_p->free_size;
        mon_p->frag_pct = 100 - mon_p->frag_pct;
    }
    else {
        mon_p->frag_pct = 0; /*no fragmentation if all the RAM is used*/
    }

#endif
}

static void lv_mem_walker(void * ptr, size_t size, int used, void * user)
{
    LV_UNUSED(ptr);

    lv_mem_monitor_t * mon_p = user;
    if(used) {
        mon_p->used_cnt++;
    }
    else {
        mon_p->free_cnt++;
        mon_p->free_size += size;
        if(size > mon_p->free_biggest_size)
            mon_p->free_biggest_size = size;
    }
}