mirror of
https://github.com/esp8266/Arduino.git
synced 2025-06-22 08:22:04 +03:00
metric for heap fragmentation (#5090)
* +Esp.getHeapUnfragness() * only in debug mode * default value * always enable, 64->32, light 32 integer square root, comments * fix when debugging is disabled * give credits * cosmetics * fragmentation metric updates (doc, better api, added getMaxFreeBlockSize()) * api reworked, +example * fixe types, fix names * coding style fix * use astyle for example
This commit is contained in:
48
cores/esp8266/Esp-frag.cpp
Normal file
48
cores/esp8266/Esp-frag.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
Esp.cpp - ESP8266-specific APIs
|
||||
Copyright (c) 2015 Ivan Grokhotkov. All rights reserved.
|
||||
This file is part of the esp8266 core for Arduino environment.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "umm_malloc/umm_malloc.h"
|
||||
#include "umm_malloc/umm_malloc_cfg.h"
|
||||
#include "coredecls.h"
|
||||
#include "Esp.h"
|
||||
|
||||
void EspClass::getHeapStats(uint32_t* hfree, uint16_t* hmax, uint8_t* hfrag)
|
||||
{
|
||||
// L2 / Euclidian norm of free block sizes.
|
||||
// Having getFreeHeap()=sum(hole-size), fragmentation is given by
|
||||
// 100 * (1 - sqrt(sum(hole-size²)) / sum(hole-size))
|
||||
|
||||
umm_info(NULL, 0);
|
||||
uint8_t block_size = umm_block_size();
|
||||
uint32_t fh = ummHeapInfo.freeBlocks * block_size;
|
||||
if (hfree)
|
||||
*hfree = fh;
|
||||
if (hmax)
|
||||
*hmax = ummHeapInfo.maxFreeContiguousBlocks * block_size;
|
||||
if (hfrag)
|
||||
*hfrag = 100 - (sqrt32(ummHeapInfo.freeSize2) * 100) / fh;
|
||||
}
|
||||
|
||||
uint8_t EspClass::getHeapFragmentation()
|
||||
{
|
||||
uint8_t hfrag;
|
||||
getHeapStats(nullptr, nullptr, &hfrag);
|
||||
return hfrag;
|
||||
}
|
@ -24,6 +24,7 @@
|
||||
#include <memory>
|
||||
#include "interrupts.h"
|
||||
#include "MD5Builder.h"
|
||||
#include "umm_malloc/umm_malloc.h"
|
||||
|
||||
extern "C" {
|
||||
#include "user_interface.h"
|
||||
@ -171,6 +172,11 @@ uint32_t EspClass::getFreeHeap(void)
|
||||
return system_get_free_heap_size();
|
||||
}
|
||||
|
||||
uint16_t EspClass::getMaxFreeBlockSize(void)
|
||||
{
|
||||
return umm_max_block_size();
|
||||
}
|
||||
|
||||
uint32_t EspClass::getChipId(void)
|
||||
{
|
||||
return system_get_chip_id();
|
||||
|
@ -103,10 +103,13 @@ class EspClass {
|
||||
void restart();
|
||||
|
||||
uint16_t getVcc();
|
||||
uint32_t getFreeHeap();
|
||||
|
||||
uint32_t getChipId();
|
||||
|
||||
uint32_t getFreeHeap();
|
||||
uint16_t getMaxFreeBlockSize();
|
||||
uint8_t getHeapFragmentation(); // in %
|
||||
void getHeapStats(uint32_t* free = nullptr, uint16_t* max = nullptr, uint8_t* frag = nullptr);
|
||||
|
||||
const char * getSdkVersion();
|
||||
String getCoreVersion();
|
||||
String getFullVersion();
|
||||
|
@ -8,6 +8,7 @@ extern "C" {
|
||||
|
||||
// TODO: put declarations here, get rid of -Wno-implicit-function-declaration
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cont.h> // g_pcont declaration
|
||||
|
||||
extern bool timeshift64_is_set;
|
||||
@ -18,6 +19,8 @@ void tune_timeshift64 (uint64_t now_us);
|
||||
void settimeofday_cb (void (*cb)(void));
|
||||
void disable_extra4k_at_link_time (void) __attribute__((noinline));
|
||||
|
||||
uint32_t sqrt32 (uint32_t n);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
56
cores/esp8266/sqrt32.c
Normal file
56
cores/esp8266/sqrt32.c
Normal file
@ -0,0 +1,56 @@
|
||||
|
||||
#include <coredecls.h>
|
||||
#include <stdint.h>
|
||||
|
||||
uint32_t sqrt32 (uint32_t n)
|
||||
{
|
||||
// http://www.codecodex.com/wiki/Calculate_an_integer_square_root#C
|
||||
// Another very fast algorithm donated by Tristan.Muntsinger@gmail.com
|
||||
// (note: tested across the full 32 bits range, see comment below)
|
||||
|
||||
// 15 iterations (c=1<<15)
|
||||
|
||||
unsigned int c = 0x8000;
|
||||
unsigned int g = 0x8000;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if (g*g > n)
|
||||
g ^= c;
|
||||
c >>= 1;
|
||||
if (!c)
|
||||
return g;
|
||||
g |= c;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* tested with:
|
||||
*
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
int main (void)
|
||||
{
|
||||
for (uint32_t i = 0; ++i; )
|
||||
{
|
||||
uint32_t sr = sqrt32(i);
|
||||
uint32_t ifsr = sqrt(i);
|
||||
|
||||
if (ifsr != sr)
|
||||
printf("%d: i%d f%d\n", i, sr, ifsr);
|
||||
|
||||
if (!(i & 0xffffff))
|
||||
{
|
||||
printf("%i%% (0x%08x)\r", ((i >> 16) * 100) >> 16, i);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
*
|
||||
*/
|
@ -1024,6 +1024,10 @@ void ICACHE_FLASH_ATTR *umm_info( void *ptr, int force ) {
|
||||
if( UMM_NBLOCK(blockNo) & UMM_FREELIST_MASK ) {
|
||||
++ummHeapInfo.freeEntries;
|
||||
ummHeapInfo.freeBlocks += curBlocks;
|
||||
ummHeapInfo.freeSize2 += (unsigned int)curBlocks
|
||||
* (unsigned int)sizeof(umm_block)
|
||||
* (unsigned int)curBlocks
|
||||
* (unsigned int)sizeof(umm_block);
|
||||
|
||||
if (ummHeapInfo.maxFreeContiguousBlocks < curBlocks) {
|
||||
ummHeapInfo.maxFreeContiguousBlocks = curBlocks;
|
||||
@ -1761,4 +1765,13 @@ size_t ICACHE_FLASH_ATTR umm_free_heap_size( void ) {
|
||||
return (size_t)ummHeapInfo.freeBlocks * sizeof(umm_block);
|
||||
}
|
||||
|
||||
size_t ICACHE_FLASH_ATTR umm_max_block_size( void ) {
|
||||
umm_info(NULL, 0);
|
||||
return ummHeapInfo.maxFreeContiguousBlocks * sizeof(umm_block);
|
||||
}
|
||||
|
||||
size_t ICACHE_FLASH_ATTR umm_block_size( void ) {
|
||||
return sizeof(umm_block);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
@ -26,6 +26,8 @@ typedef struct UMM_HEAP_INFO_t {
|
||||
unsigned short int freeBlocks;
|
||||
|
||||
unsigned short int maxFreeContiguousBlocks;
|
||||
|
||||
unsigned int freeSize2;
|
||||
}
|
||||
UMM_HEAP_INFO;
|
||||
|
||||
@ -41,6 +43,8 @@ void *umm_realloc( void *ptr, size_t size );
|
||||
void umm_free( void *ptr );
|
||||
|
||||
size_t umm_free_heap_size( void );
|
||||
size_t umm_max_block_size( void );
|
||||
size_t umm_block_size( void );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
Reference in New Issue
Block a user