1
0
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:
david gauchard
2018-09-10 06:50:01 +02:00
committed by Develo
parent bbaea5a358
commit ce28a76a24
11 changed files with 227 additions and 5 deletions

View 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;
}

View File

@ -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();

View File

@ -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();

View File

@ -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
View 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");
}
*
*/

View File

@ -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);
}
/* ------------------------------------------------------------------------ */

View File

@ -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
}