toit

How to interpret Toit out of memory error


I am using Toit with an ESP32 eval board (ESP32_DevKitc_V4). The board is connected to another device through a UART and it is publishing to an MQTT service. Every once in a while I get a memory leak error like the following:

Screenshot

Heap report @ out of memory:
  ┌───────────┬─────────┬───────────────────────┐
  │   Bytes   │  Count  │  Type                 │
  ├───────────┼─────────┼───────────────────────┤
  |     784   |      6  |  external byte array  |
  |   73728   |     18  |  toit                 |
  |    5016   |     25  |  lwip                 |
  |    7144   |    585  |  heap overhead        |
  |    8088   |     49  |  event source         |
  |    4472   |    122  |  other threads        |
  |   20744   |     25  |  thread spawn         |
  |   48368   |    184  |  null tag             |
  |   42896   |    112  |  wifi                 |
  └───────────┴─────────┴───────────────────────┘
  Total: 211240 bytes in 541 allocations (85%)

How do I interpret this? Is there something in the above table that stands out?


Solution

  • Firstly I'll assume that you are running on the latest release, so that you have the new sliding-compacting GC. Otherwise you should do that because it saves quite a lot of memory. Do you know which version you are running?

    It looks like you still have about 30k free, so if you are running out of memory then it's because you have fragmentation. Some fragmentation is inevitable, so there may not be anything to do about that. The Toit heap needs 4k at a time to expand so any free areas smaller than that can't be used. If you are creating large byte arrays (eg 8k) then they will also need large free areas to be created.

    Unfortunately the other numbers don't jump out at me. These are fairly normal numbers. Some memory is taken at boot time for static buffers, and for timing critical code (interrupt handlers, wifi drivers, etc.) that are moved from flash to IRAM for performance reasons. That's why you start off with 211k, not 512k. The "null tag" memory is allocations that we have not yet instrumented and don't know the source of.

    You may want to try running the print_objects function to see what is filling up your Toit heap. It prints a histogram with the most popular objects on the heap. Sadly as of June 2022 it gives you class numbers instead of class names. If you hop on the Discord https://discord.gg/Q7Y9VQ5nh2 we can probably help you decode the class numbers.