Memory Test for memory leak or fragmentation

Hi,

Is there a simple method to test for memory leaks/heap fragmentation. I would like to add a piece of code that can monitor and report on it.

Thanks

Is it not better to use retained memory rather than EEPROM to prevent memory problems in general ?

For your first question, System.freeMemory() will help you find out whether your code suffers from a memory leak, but heap fragmentation is more complicated as you’d need to travers the entire heap map and see how many fragments you have and what their individual size is and compare that against any chunk of dynamic memory “someone” may want to allocate.

For the second question, that depends on your use case. EEPROM survives a total power loss, retained memory doesn’t.
EEPROM can be filled with data on the fly, for retained you need to predefine some static variable to place into the retained area for your data to be held.

1 Like

Thanks

    runtime_info_t info;
    memset(&info, 0, sizeof(info));
    info.size = sizeof(info);
    HAL_Core_Runtime_Info(&info, NULL);

Now the runtime info struct has some more memory info, one of which is largest free block. That seems like a good indicator of fragmentation!

2 Likes

Thanks a lot. After some testing it seems the largest_free_block_heap is always 87496 in setup and plus minus 87248 just before the Electron goes to sleep. The other parameters stays constant.

@jamesza could you share your code how you determined the free block? I believe I could use this to determine fragmentation

Measuring the fragmentation

There are several formal definitions for the fragmentation; in this article, I’ll use this simple definition:

Fragmentation's formula

Let’s try some numbers in this formula. Suppose you have 1KB of free RAM.

  • At 0% (no fragmentation), you can allocate 1KB in one shot.
  • At 25%, you can allocate 750B in one shot.
  • At 50%, you can only allocate 500B in one shot.
  • At 75%, you can only allocate 250B in one shot.

A value of 50% or more is considered high and can seriously impede your program, as we’ll see

Currently I only monitor the largest_free_block_heap of every Electron in the field as an indicator and its is about 86640. The rest of the parameters is 100% constant. I use the code exactly as used by Elco.

runtime_info_t info;

memset(&info, 0, sizeof(info));
info.size = sizeof(info);
HAL_Core_Runtime_Info(&info, NULL);
Serial.println("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
Serial.println(info.size);
Serial.println(info.flags);
Serial.println(info.system_version);
Serial.println(info.total_init_heap);
Serial.println(info.total_heap);
Serial.println(info.max_used_heap);
Serial.println(info.user_static_ram);
Serial.println(info.largest_free_block_heap);
Serial.println("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^");
1 Like

Here’s a function I made to check fragmentation percent and will reset the device if it gets above 50%

void fragmentationCheck() {
  static uint32_t free_memory = 0;
  static uint32_t largest_block = 0;
  static uint32_t prevCheckMillis = 0;
  static uint8_t fragmentationPercent = 0;
  static bool printRightAway = true;

  if (millis() - prevCheckMillis > (60000 * 1) || printRightAway) {
    runtime_info_t info;
    memset(&info, 0, sizeof(info));
    info.size = sizeof(info);
    HAL_Core_Runtime_Info(&info, NULL);
    largest_block = info.largest_free_block_heap;

    free_memory = System.freeMemory();
    fragmentationPercent = (largest_block/free_memory)*100;
    char memoryCharArray[30];
    snprintf(memoryCharArray, sizeof(memoryCharArray),
      "%u.%u.%u.%u"
      , free_memory
      , largest_block
      , fragmentationPercent
      , Time.now()
    );
    Serial.println(memoryCharArray); //todo Remove
    prevCheckMillis = millis();
    printRightAway = false;
  }
  
  if (fragmentationPercent > 50) {
    System.reset();
  }
}

Tx I am going to test and will give feedback in a few days.