Сколько накладных расходов добавляют декораторы к вызовам функций Python - PullRequest
17 голосов
/ 23 августа 2010

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

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

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

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

Ответы [ 3 ]

13 голосов
/ 23 августа 2010

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

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

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

5 голосов
/ 23 августа 2010

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

@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's normal)
        func()  # This will be a second function call, after the call to decorated_func()
    return decorated_func

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

3 голосов
/ 23 августа 2010

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

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

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

Декорированная функция состоит из двух частей.

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

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

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

...