Измерьте максимальное использование памяти во время вызова функции

У меня есть библиотека Linux/Mac C++, которая выполняет серию шагов в виде вызовов функций. Я хотел бы измерить максимальное использование памяти на каждом этапе.

Меня не интересуют специальные решения, такие как запуск другого потока, который опрашивает использование памяти, запуск профилировщика и т. Д.

Пока я нашел getrusage() присутствует в Mac и Linux и возвращает максимальное использование памяти, однако, кажется, нет способа сбросить этот максимум после каждого вызова функции.

Есть ли способ обойти это ограничение?

Редактировать: чтобы быть ясно, я не хочу командовать malloc()/free() и войти все. Я хочу решение, которое подходит для запуска производственного кода.

2 ответа

Решение

Я просмотрел исходный код Linux и нашел это:

        /*
         * Writing 5 to /proc/pid/clear_refs resets the peak
         * resident set size to this mm's current rss value.
         */

Я еще не пробовал, но выглядит многообещающе.

Редактировать: он был добавлен в этот коммит

Редактировать 2: я посмотрел исходный код ядра MacOS - соответствующее значение хранится в resident_max, К сожалению, кажется, что нет функции, чтобы сбросить его.

Редактировать 3: В Linux вы можете получить максимально выделенную память, используя malloc_info() однако, кажется, нет способа сбросить его. Это также зависит от вас, используя glibc,

malloc а также free звонки - это не просто тривиальные обертки sbrk а также mmap системные вызовы. Это делает getrusage вернуть то, что не соответствует звонкам malloc а также free, Любая нетривиальная реализация этих функций будет управлять свободным списком внутри самого процесса, прежде чем думать о возврате чего-либо в систему.

Программа вызывает free (или же delete в этом отношении), и память не сразу возвращается операционной системе (возможно, никогда). free память может быть повторно использована задачей, если она вызывает malloc, но не другими процессами. Это делает getrusage правильный с точки зрения ОС, но не правильный с точки зрения программы.

В Linux вы можете использовать mallinfo()

#include <malloc.h>
#include <cinttypes>
std::size_t memsize()
{
    auto data = mallinfo();
    return data.arena - data.fordblks + data.hblkhd;
}

Вот, memsize() вернет количество байтов, выделенных с точки зрения программы. Он учитывает различные методы распределения, такие как sbrk а также mmap и рассматривает округление и издержки как часть выделенной памяти malloc() (а также new).

С OSX все не так ярко. Вы можете взглянуть на исходный код яблочной функции malloc() и, в частности, на mstats, который гласит в комментарии:

/*
 * A Glibc-like mstats() interface.
 *
 * Note that this interface really isn't very good, as it doesn't understand
 * that we may have multiple allocators running at once.  We just massage
 * the result from malloc_zone_statistics in any case.
 */

Это выглядит не очень многообещающе и:

#include <malloc/malloc.h>
#include <cinttypes>
std::size_t memsize()
{
    auto data = mstats();
    return data.bytes_used;
}

По моим экспериментам выглядит не очень хорошо. Но это может быть лучше, чем ничего, или просто полагаться на getrusage, Я думаю, что вам не повезло на OSX, если кто-то не может исправить меня.

Другие вопросы по тегам