diff --git a/components/heap/test/CMakeLists.txt b/components/heap/test/CMakeLists.txt new file mode 100644 index 00000000..0c37e41b --- /dev/null +++ b/components/heap/test/CMakeLists.txt @@ -0,0 +1,6 @@ +set(COMPONENT_SRCDIRS ".") +set(COMPONENT_ADD_INCLUDEDIRS ".") + +set(COMPONENT_REQUIRES unity heap esp8266) + +register_component() \ No newline at end of file diff --git a/components/heap/test/component.mk b/components/heap/test/component.mk new file mode 100644 index 00000000..5dd172bd --- /dev/null +++ b/components/heap/test/component.mk @@ -0,0 +1,5 @@ +# +#Component Makefile +# + +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive diff --git a/components/heap/test/test_heap_effectivity.c b/components/heap/test/test_heap_effectivity.c new file mode 100644 index 00000000..51e596d1 --- /dev/null +++ b/components/heap/test/test_heap_effectivity.c @@ -0,0 +1,119 @@ +// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include <stdint.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> +#include <sys/param.h> + +#include <unity.h> + +#include "esp_attr.h" +#include "esp8266/eagle_soc.h" + +#include "esp_heap_caps.h" + +#define MIXED_HEAP_LIST_NOTES 64 + +#define TIME_US_REG 0x3ff20c00 + +static inline uint32_t get_us(void) +{ + return REG_READ(TIME_US_REG); +} + +static void* IRAM_ATTR test_alloc_time_in_us(size_t n, uint32_t *time) +{ + void *p; + uint32_t t; + + t = get_us(); + + p = heap_caps_malloc(n, MALLOC_CAP_8BIT); + if (!p) + return NULL; + + *time += get_us() - t; + + return p; +} + +static void IRAM_ATTR test_free_time_in_us(void *p, uint32_t *time) +{ + uint32_t t; + + t = get_us(); + + heap_caps_free(p); + + *time += get_us() - t; +} + +static void IRAM_ATTR test_heap_effectivity(uint32_t *time, uint32_t *count) +{ + int cnt = 0; + uint32_t alloc_us = 0, free_us = 0; + + for (; cnt < INT32_MAX; cnt++) { + void *p = test_alloc_time_in_us(cnt + sizeof(void *) + 1, &alloc_us); + if (!p) + break; + test_free_time_in_us(p, &free_us); + } + + time[0] = alloc_us; + time[1] = free_us; + count[0] = cnt; +} + +static void test_heap_init(uint32_t *pbuf) +{ + for (int i = 0; i < MIXED_HEAP_LIST_NOTES; i++) { + pbuf[i] = (uint32_t)heap_caps_malloc(1, MALLOC_CAP_8BIT); + assert(pbuf[i]); + } + + for (int i = 0; i < MIXED_HEAP_LIST_NOTES; i += 2) { + heap_caps_free((void *)pbuf[i]); + pbuf[i] = 0; + } +} + +static void test_heap_deinit(uint32_t *pbuf) +{ + for (int i = 0; i < MIXED_HEAP_LIST_NOTES; i++) { + if (pbuf[i]) { + heap_caps_free((void *)pbuf[i]); + pbuf[i] = 0; + } + } +} + +TEST_CASE("Test Heap alloc/free effectivity", "[Heap]") +{ + uint32_t time_in_us[2], count; + uint32_t buf[MIXED_HEAP_LIST_NOTES]; + + test_heap_init(buf); + + test_heap_effectivity(time_in_us, &count); + + printf("Each alloc costs time %u us, each free costs time %u us\n", time_in_us[0] / count, time_in_us[1] / count); + + test_heap_deinit(buf); +} + +// Enable Heap Trace : Each alloc costs time 27 us, each free costs time 5 us +// Disable Heap Trace : Each alloc costs time 18 us, each free costs time 4 us