Created
July 13, 2020 20:40
-
-
Save tadeu/95013963c64da4cd74a2c6f4fa4fd553 to your computer and use it in GitHub Desktop.
Getting number of bytes allocated in heap in Linux
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <cstdio> | |
#include <cstdlib> | |
#include <cstring> | |
#include <malloc.h> | |
size_t get_attribute_value(const char *str, const char *substr) | |
{ | |
const char *pos = strstr(str, substr); | |
if (pos == nullptr) { | |
return 0; | |
} | |
pos += strlen(substr); | |
char* next_pos = nullptr; | |
size_t value = strtoull(pos, &next_pos, 10); | |
if (next_pos == nullptr || next_pos == pos) { | |
return 0; | |
} | |
return value; | |
} | |
size_t get_attribute_value(const char *str, const char *first_substr, const char* second_substr) | |
{ | |
const char *pos = strstr(str, first_substr); | |
if (pos == nullptr) { | |
return 0; | |
} | |
pos += strlen(first_substr); | |
pos = strstr(pos, second_substr); | |
if (pos == nullptr) { | |
return 0; | |
} | |
pos += strlen(second_substr); | |
char* next_pos = nullptr; | |
size_t value = strtoull(pos, &next_pos, 10); | |
if (next_pos == nullptr || next_pos == pos) { | |
return 0; | |
} | |
return value; | |
} | |
size_t get_total_heap_bytes() | |
{ | |
// There are three functions in Linux libc API to retrieve heap | |
// information: `malloc_stats`, `mallinfo` and `malloc_info`. | |
// The first two are still broken for 64-bit systems and will | |
// report wrong values if there are more than 4 Gb of allocated | |
// memory. The latter works for more than 4 Gb, but it outputs | |
// a XML to a file, so `open_memstream` is used to avoid writing | |
// to the disk, and a very simple "parsing" is done here using | |
// C-string search. | |
// | |
// More info: | |
// https://stackoverflow.com/questions/40878169/64-bit-capable-alternative-to-mallinfo | |
// https://stackoverflow.com/questions/3903807/how-does-malloc-info-work | |
// https://stackoverflow.com/questions/34292457/gnu-malloc-info-get-really-allocated-memory | |
char* buf = nullptr; | |
size_t buf_size = 0; | |
FILE* f = open_memstream(&buf, &buf_size); | |
malloc_info(0, f); | |
fclose(f); | |
// We are only interested in totals, so we skip everything until the | |
// closing of the <heap>...</heap> block. | |
const char* pos = strstr(buf, "</heap>"); | |
// rest and fast are blocks that have been freed, we should subtract them | |
size_t rest = get_attribute_value(pos, "<total type=\"rest\" count=\"", "\" size=\""); | |
size_t fast = get_attribute_value(pos, "<total type=\"fast\" count=\"", "\" size=\""); | |
// mmap and current are totals (mmap is used for very large blocks) | |
size_t mmap = get_attribute_value(pos, "<total type=\"mmap\" count=\"", "\" size=\""); | |
size_t current = get_attribute_value(pos, "<system type=\"current\" size=\""); | |
auto free_mem = rest + fast; | |
auto total_mem = mmap + current; | |
size_t allocated_mem = total_mem > free_mem ? total_mem - free_mem : 0; | |
free(buf); | |
buf = nullptr; | |
return allocated_mem; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment