diff --git a/src/MicroOcpp/Core/ConfigurationContainerFlash.cpp b/src/MicroOcpp/Core/ConfigurationContainerFlash.cpp index 204765de..d690d630 100644 --- a/src/MicroOcpp/Core/ConfigurationContainerFlash.cpp +++ b/src/MicroOcpp/Core/ConfigurationContainerFlash.cpp @@ -75,7 +75,7 @@ class ConfigurationContainerFlash : public ConfigurationContainer, public AllocO return save(); } - auto doc = FilesystemUtils::loadJson(filesystem, getFilename()); + auto doc = FilesystemUtils::loadJson(filesystem, getFilename(), getMemoryTag()); if (!doc) { MO_DBG_ERR("failed to load %s", getFilename()); return false; @@ -130,7 +130,14 @@ class ConfigurationContainerFlash : public ConfigurationContainer, public AllocO config = nullptr; } if (!config) { - key_pooled = static_cast(MO_MALLOC(key, strlen(key) + 1)); + #if MO_ENABLE_HEAP_PROFILER + char memoryTag [64]; + snprintf(memoryTag, sizeof(memoryTag), "%s%s", "v16.Configuration.", key); + #else + const char *memoryTag = nullptr; + (void)memoryTag; + #endif + key_pooled = static_cast(MO_MALLOC(memoryTag, strlen(key) + 1)); if (!key_pooled) { MO_DBG_ERR("OOM: %s", key); return false; diff --git a/src/MicroOcpp/Core/FilesystemUtils.cpp b/src/MicroOcpp/Core/FilesystemUtils.cpp index 77748e2e..f18b5643 100644 --- a/src/MicroOcpp/Core/FilesystemUtils.cpp +++ b/src/MicroOcpp/Core/FilesystemUtils.cpp @@ -9,7 +9,7 @@ using namespace MicroOcpp; -std::unique_ptr FilesystemUtils::loadJson(std::shared_ptr filesystem, const char *fn) { +std::unique_ptr FilesystemUtils::loadJson(std::shared_ptr filesystem, const char *fn, const char *memoryTag) { if (!filesystem || !fn || *fn == '\0') { MO_DBG_ERR("Format error"); return nullptr; @@ -56,7 +56,7 @@ std::unique_ptr FilesystemUtils::loadJson(std::shared_ptr loadJson(std::shared_ptr filesystem, const char *fn); +std::unique_ptr loadJson(std::shared_ptr filesystem, const char *fn, const char *memoryTag = nullptr); bool storeJson(std::shared_ptr filesystem, const char *fn, const MemJsonDoc& doc); bool remove_if(std::shared_ptr filesystem, std::function pred); diff --git a/src/MicroOcpp/Core/Memory.cpp b/src/MicroOcpp/Core/Memory.cpp index 5386268f..adf8066c 100644 --- a/src/MicroOcpp/Core/Memory.cpp +++ b/src/MicroOcpp/Core/Memory.cpp @@ -18,47 +18,104 @@ struct MemBlockInfo { updateTag(ptr, tag); } - void updateTag(void* ptr, const char *tag) { - if (!tag) { - return; - } - if (tagger_ptr == nullptr || ptr < tagger_ptr) { - MO_DBG_DEBUG("update tag from %s to %s, ptr from %p to %p", this->tag.c_str(), tag, tagger_ptr, ptr); - tagger_ptr = ptr; - this->tag = tag; + void updateTag(void* ptr, const char *tag); +}; + +std::map memBlocks; //key: memory address of malloc'd block + +struct MemTagInfo { + size_t current_size = 0; + size_t max_size = 0; + + MemTagInfo(size_t size) { + operator+=(size); + } + + void operator+=(size_t size) { + current_size += size; + max_size = std::max(max_size, current_size); + } + + void operator-=(size_t size) { + if (size > current_size) { + MO_DBG_ERR("captured size does not fit"); + //return; let it happen for now } + current_size -= size; } }; -std::map memBlocks; //key: memory address of malloc'd block +std::map memTags; + +size_t memTotal, memTotalMax; + +void MemBlockInfo::updateTag(void* ptr, const char *tag) { + if (!tag) { + return; + } + if (tagger_ptr == nullptr || ptr < tagger_ptr) { + MO_DBG_VERBOSE("update tag from %s to %s, ptr from %p to %p", this->tag.c_str(), tag, tagger_ptr, ptr); + + auto tagInfo = memTags.find(this->tag); + if (tagInfo != memTags.end()) { + tagInfo->second -= size; + } + + tagInfo = memTags.find(tag); + if (tagInfo != memTags.end()) { + tagInfo->second += size; + } else { + memTags.emplace(tag, size); + } + + tagger_ptr = ptr; + this->tag = tag; + } +} #endif //MO_ENABLE_HEAP_PROFILER void mo_mem_deinit() { #if MO_ENABLE_HEAP_PROFILER memBlocks.clear(); + memTags.clear(); #endif } void *mo_mem_malloc(const char *tag, size_t size) { - MO_DBG_DEBUG("malloc %zu B (%s)", size, tag ? tag : "unspecified"); + MO_DBG_VERBOSE("malloc %zu B (%s)", size, tag ? tag : "unspecified"); auto ptr = malloc(size); #if MO_ENABLE_HEAP_PROFILER if (ptr) { memBlocks.emplace(ptr, MemBlockInfo(ptr, tag, size)); + + memTotal += size; + memTotalMax = std::max(memTotalMax, memTotal); } #endif return ptr; } void mo_mem_free(void* ptr) { - MO_DBG_DEBUG("free"); + MO_DBG_VERBOSE("free"); #if MO_ENABLE_HEAP_PROFILER if (ptr) { - memBlocks.erase(ptr); + + auto blockInfo = memBlocks.find(ptr); + if (blockInfo != memBlocks.end()) { + auto tagInfo = memTags.find(blockInfo->second.tag); + if (tagInfo != memTags.end()) { + tagInfo->second -= blockInfo->second.size; + } + memTotal -= blockInfo->second.size; + } + + if (blockInfo != memBlocks.end()) { + memBlocks.erase(blockInfo); + } } #endif free(ptr); @@ -67,7 +124,7 @@ void mo_mem_free(void* ptr) { #if MO_ENABLE_HEAP_PROFILER void mo_mem_set_tag(void *ptr, const char *tag) { - MO_DBG_DEBUG("set tag (%s)", tag ? tag : "unspecified"); + MO_DBG_VERBOSE("set tag (%s)", tag ? tag : "unspecified"); if (!tag) { return; @@ -88,7 +145,7 @@ void mo_mem_set_tag(void *ptr, const char *tag) { } if (!hasTagged) { - MO_DBG_DEBUG("memory area doesn't apply"); + MO_DBG_VERBOSE("memory area doesn't apply"); } } @@ -127,7 +184,13 @@ void mo_mem_print_stats() { printf("%s - %zu B\n", tag.first.c_str(), tag.second); } - printf("Blocks: %zu\nTotal usage: %zu B\nTags: %zu\nTotal tagged: %zu B\nUntagged: %zu\nTotal untagged: %zu B\n", memBlocks.size(), size, tags.size(), size_control, untagged, untagged_size); + size_t size_control2 = 0; + for (const auto& tag : memTags) { + size_control2 += tag.second.current_size; + printf("%s - %zu B (max. %zu B)\n", tag.first.c_str(), tag.second.current_size, tag.second.max_size); + } + + printf("Blocks: %zu\nTotal usage: %zu B\nTags: %zu\nTotal tagged: %zu B\nTags2: %zu\nTotal tagged2: %zu B\nUntagged: %zu\nTotal untagged: %zu B\nCurrent usage: %zu B\nMaximum usage: %zu B\n", memBlocks.size(), size, tags.size(), size_control, memTags.size(), size_control2, untagged, untagged_size, memTotal, memTotalMax); } #endif //MO_ENABLE_HEAP_PROFILER diff --git a/src/MicroOcpp/Core/Memory.h b/src/MicroOcpp/Core/Memory.h index e57ce218..932779a3 100644 --- a/src/MicroOcpp/Core/Memory.h +++ b/src/MicroOcpp/Core/Memory.h @@ -140,11 +140,11 @@ class AllocOverrider { } public: void *operator new(size_t size) { - MO_DBG_DEBUG("AllocOverrider new %zu B", size); + MO_DBG_VERBOSE("AllocOverrider new %zu B", size); return MO_MALLOC(nullptr, size); } void operator delete(void * ptr) { - MO_DBG_DEBUG("AllocOverrider delete"); + MO_DBG_VERBOSE("AllocOverrider delete"); MO_FREE(ptr); } @@ -206,7 +206,7 @@ struct Allocator { } T *allocate(size_t count) { - MO_DBG_DEBUG("Allocator allocate %zu B (%s)", sizeof(T) * count, tag ? tag : "unspecified"); + MO_DBG_VERBOSE("Allocator allocate %zu B (%s)", sizeof(T) * count, tag ? tag : "unspecified"); return static_cast( MO_MALLOC( #if MO_ENABLE_HEAP_PROFILER @@ -217,7 +217,7 @@ struct Allocator { sizeof(T) * count)); } void deallocate(T *ptr, size_t count) { - MO_DBG_DEBUG("Allocator deallocate %zu B (%s)", sizeof(T) * count, tag ? tag : "unspecified"); + MO_DBG_VERBOSE("Allocator deallocate %zu B (%s)", sizeof(T) * count, tag ? tag : "unspecified"); MO_FREE(ptr); } @@ -342,7 +342,7 @@ class ArduinoJsonAllocator { } void *allocate(size_t size) { - MO_DBG_DEBUG("ArduinoJsonAllocator allocate %zu B (%s)", size, tag ? tag : "unspecified"); + MO_DBG_VERBOSE("ArduinoJsonAllocator allocate %zu B (%s)", size, tag ? tag : "unspecified"); return MO_MALLOC( #if MO_ENABLE_HEAP_PROFILER tag, @@ -352,7 +352,7 @@ class ArduinoJsonAllocator { size); } void deallocate(void *ptr) { - MO_DBG_DEBUG("ArduinoJsonAllocator deallocate"); + MO_DBG_VERBOSE("ArduinoJsonAllocator deallocate"); MO_FREE(ptr); } }; @@ -361,7 +361,7 @@ using MemJsonDoc = BasicJsonDocument; template T *mo_mem_new(const char *tag, Args&& ...args) { - MO_DBG_DEBUG("mo_mem_new %zu B (%s)", sizeof(T), tag ? tag : "unspecified"); + MO_DBG_VERBOSE("mo_mem_new %zu B (%s)", sizeof(T), tag ? tag : "unspecified"); if (auto ptr = MO_MALLOC(tag, sizeof(T))) { return new(ptr) T(std::forward(args)...); } @@ -370,7 +370,7 @@ T *mo_mem_new(const char *tag, Args&& ...args) { template void mo_mem_delete(T *ptr) { - MO_DBG_DEBUG("mo_mem_delete"); + MO_DBG_VERBOSE("mo_mem_delete"); if (ptr) { ptr->~T(); MO_FREE(ptr);