Подтвердить что ты не робот

Сколько накладных расходов делают декораторы для вызова функций Python

Я играл с декоратором времени для моего приложения pylons, чтобы предоставлять информацию о времени полета для определенных функций. Я сделал это, создав декоратор и просто привязав его к любой функции в контроллере, который я хочу выполнить по времени.

Было указано, однако, что декораторы могут добавить к вызову достаточное количество накладных расходов и что они работают на 2-3 раза медленнее, чем некорректированная функция.

Во-первых, я ожидал бы, что выполнение декорированной функции займет больше времени, чем неупорядоченный, но я ожидаю, что накладные расходы будут в тысячные доли секунды и будут незначительными по сравнению с вызовом вставки SQL. Сам декоратор выполняет простые простые вычисления времени, используя time.time() и некоторую очень простую агрегацию.

Делают ли декораторы значительные накладные расходы на систему? Я не могу найти ничего, чтобы поддержать это.

4b9b3361

Ответ 1

Накладные расходы, добавленные с помощью декоратора, должны быть только одним дополнительным вызовом функции.

Работа, выполняемая декоратором, не является частью служебных данных, так как ваша альтернатива заключается в том, чтобы добавить эквивалентный код к украшенному объекту.

Таким образом, возможно, что функция decorate занимает в два раза больше времени, но это потому, что декоратор выполняет важную работу, которая занимает примерно одно и то же время, чтобы весело провести время, как непривязанная функция.

Ответ 2

Важно знать, что декоратор имеет простой эффект:

@decorator
def f():
    …

- это просто синтаксический сахар для

def f():
    …
f = decorator(f)

Таким образом, если декоратор ничего не делает, у вас нет накладных расходов при вызове декорированной функции (вызов decorator(f) занимает немного времени, хотя), как в

decorator = lambda func: func
@decorator
def f():
    …

Если декоратор что-либо делает, вы получаете только время, затраченное декоратором. Обычно это включает дополнительный вызов функции (функции декорированной функции), как в

def decorator(func):
    def decorated_func():
        print "Before calling function", func  # Some overhead (but that normal)
        func()  # This will be a second function call, after the call to decorated_func()
    return decorated_func

Таким образом, само по себе украшение функции не добавляет больших накладных расходов для того, что вы хотите сделать: единственные очевидные накладные расходы, которые вы могли бы в принципе удалить, заключались бы в том, чтобы не вызвать func() в украшенной функции, а вместо этого скопировать его полный кода, но четкость кода будет страдать (разборчивость и гибкость - вот некоторые из причин, по которым декораторы существуют в первую очередь).

Ответ 3

Делают ли декораторы значительные накладные расходы на систему? Я не могу найти ничего, чтобы поддержать это.

Они добавляют почти никаких измеримых накладных расходов. Ноль.

Важно отметить, что декоратор работает один раз, чтобы создать украшенную функцию. Один раз.

У декорированной функции есть две части.

  • любое украшение было добавлено. Это не накладные расходы.

  • плюс оригинальная функция. Это не накладные расходы.

Там нет реальных накладных расходов. Вы можете - с некоторой осторожностью - быть в состоянии измерить накладные расходы на один дополнительный вызов функции и возврата как часть украшенной функции, но это почти неизмеримо мало. И это, вероятно, гораздо меньше, чем альтернативный дизайн, который не использует украшения.