(Примечание: Следующая упоминает execinfo/ backtrace
, но это только пример, поведение в вопросе появились с различными библиотеками..)Backtrace Запросы крайне медленно
Рассмотрим библиотеку утилита, которая отслеживает выделение ресурсов некоторого приложения, связанного с ним. Поскольку функции выделяют и освобождают ресурсы, они вызывают функцию отслеживания, которая записывает детали операции, а также некоторую информацию, которая может быть использована для восстановления пути вызова. Иногда запрашивается библиотека для разбивки операций по путям вызовов.
В настройках этого вопроса отслеживание должно быть низким накладные расходы, но запросы не обязательно. Следовательно, для отслеживания я сохранил минимальную информацию, идентифицирующую путь вызова, например, путем вызова execinfo/ backtrace
. Перевод символов, распутывание и т. Д., Откладываются на запросы и не являются частью этого вопроса.
К моему удивлению, просто вызов backtrace
замедлял выполнение на ~ 4000% (!) Относительно вызова malloc
. Поскольку backtrace
принимает заданную (максимальную) глубину стека в качестве аргумента, и ее можно вызвать по путям вызовов с разными глубинами стека, я попытался понять, как эти параметры влияют на ее производительность. Насколько я вижу, просто вызов этой функции каким-либо образом имеет огромный штраф.
Для измерений я написал следующий простой код (см также full version):
const size_t max_backtrace_size = 100;
void *backtrace_buf[max_backtrace_size];
static void track()
{
if(backtrace_size > 0)
::backtrace(backtrace_buf, backtrace_size);
}
static void op(size_t i)
{
if(i == 0)
{
track();
return;
}
op(i - 1);
}
Первый из этих двух функций, track
, моделирует фактическое отслеживание (обратите внимание, что backtrace_size == 0
полностью отключает вызов backtrace
); второй, op
- это рекурсия, которая завершается вызовом track
. Используя эти две функции, я изменил параметры и измерил результаты (см. Также the IPython Notebook).
На следующем рисунке показано время отслеживания в зависимости от разных размеров стека для каждого вызова backtrace
с backtrace_size == 1
или не называть его (у которого такое малое время, что оно лежит на оси X, и его вряд ли можно увидеть на рисунке). backtrace
имеет огромные накладные расходы, даже если вызывается с небольшими параметрами.
На приведенном ниже рисунке дополнительно показывает накладные расходы, в настоящее время в зависимости от размера, так и трассировки глубины стеки. Опять же, есть огромный прыжок, просто называя эту функцию.
Есть ли какой-либо технический способ уменьшить накладные расходы нахождения трассировки? (возможно, в другой библиотеке или в разных настройках сборки.)
В отсутствие 1. существует ли совершенно другая жизнеспособная альтернатива проблеме наверху?
Спасибо за ваш ответ! Многое из того, что вы написали в начале re. относительные накладные расходы являются правильными, но, к сожалению, это связано с моим непреднамеренным отсутствием относительных накладных расходов на вызов '' malloc'' (я исправлю это в вопросе - спасибо).О выборке - вот что я в итоге сделал. Ваша мысль о указателе фрейма стека особенно освещается для него, и я буду читать дальше. –