Add Max Used memory to lv_mem_monitor_t

Hi

Think that could be useful to add to the lv_mem_monitor_t struct a filed with the maximum total size of allocated memory.

This could be useful to determine the size of LV_MEM_SIZE in memory constraint systems without be necessary to “reduce” the size and wait when problems start.

I have already implemented it, just not sure if it was the best place.

  • Added new field to lv_mem_monitor_t
typedef struct {
    uint32_t total_size; /**< Total heap size */
    uint32_t free_cnt;
    uint32_t free_size; /**< Size of available memory */
    uint32_t free_biggest_size;
    uint32_t used_cnt;
    uint32_t max_use; /**< Max size of Heap memory used */
    uint8_t used_pct; /**< Percentage used */
    uint8_t frag_pct; /**< Amount of fragmentation */
} lv_mem_monitor_t;
  • Added local variable to lvmem.c and initialize to 0
static uint32_t mem_max_size;

void _lv_mem_init(void)
{
#if LV_MEM_CUSTOM == 0

#if LV_MEM_ADR == 0
  /*Allocate a large array to store the dynamically allocated data*/
  static LV_MEM_ATTR MEM_UNIT work_mem_int[LV_MEM_SIZE / sizeof(MEM_UNIT)];
  work_mem = (uint8_t*) work_mem_int;
#else
    work_mem = (uint8_t *)LV_MEM_ADR;
#endif
    mem_max_size = 0;
  lv_mem_ent_t *full = (lv_mem_ent_t*) work_mem;
  full->header.s.used = 0;
  /*The total mem size id reduced by the first header and the close patterns */
  full->header.s.d_size = LV_MEM_SIZE - sizeof(lv_mem_header_t);
#endif
}
  • calculate the used memory and update the variable in lv_mem_alloc
if (alloc == NULL) {
    LV_LOG_WARN("Couldn't allocate memory");
  } else {
    /* just a safety check, it is not suppose to happen */
    if ((uint32_t) alloc > (uint32_t) work_mem) {
      if ((((uint32_t) alloc - (uint32_t) work_mem) + size) > mem_max_size) {
        mem_max_size = ((uint32_t) alloc - (uint32_t) work_mem) + size;
      }
    }
  }
  • And update the lv_mem_monitor to use it
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
  lv_mem_ent_t *e;
  e = NULL;

  e = ent_get_next(e);

  while (e != NULL) {
    if (e->header.s.used == 0) {
      mon_p->free_cnt++;
      mon_p->free_size += e->header.s.d_size;
      if (e->header.s.d_size > mon_p->free_biggest_size) {
        mon_p->free_biggest_size = e->header.s.d_size;
      }
    } else {
      mon_p->used_cnt++;
    }

    e = ent_get_next(e);
  }
  mon_p->max_use = mem_max_size;
  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 = (uint32_t) 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
}

If useful i can try to make a pull request on GitHub.

Thank You

This can already be calculated pretty easily. The percentage of memory used is already available. All that’s left to do is to multiply LV_MEM_SIZE by that percentage. I’m not sure if it’s worth adding another field to lv_mem_monitor_t for a calculation like this.

Hi

Doesn’t the percentage indicates the current used memory?

In this case my intention is to know the maximum memory used from the pool, to determine the minimum size i can define.

For example, running the “demo_printer”, after a couple interaction i have:

LVGL_MEM -> used: 7864 ( 16 %), frag: 7 %, biggest free: 38604, max used: 20600

in this case, while running this demo, i know that the LV_MEM_SIZE would need to be at least 20600 bytes, altough at the moment the used memory is only 7864bytes (16%).

2 Likes

Oh… I understand. I initially thought you were just taking a snapshot of the currently used memory.

This feature would definitely be useful. Go ahead and send a pull request. :slightly_smiling_face: