2010-08-23 15 views
17

He estado jugando con un decorador de sincronización para mi aplicación de pilones para proporcionar información de sincronización sobre la marcha para funciones específicas. Lo hice creando un decorador & simplemente adjuntándolo a cualquier función en el controlador que desee sincronizar.Cuánta sobrecarga agregan los decoradores a las llamadas a función de Python

Se ha señalado, sin embargo, que los decoradores pueden agregar una cantidad considerable de sobrecarga a la llamada, y que corren 2-3 veces más lento que una función no decorada.

En primer lugar, esperaría que la ejecución de una función decorada durara más que una sin decorar, pero esperaría que la sobrecarga en las milésimas de segundos & sea insignificante en comparación con una llamada de inserción de SQL. El decorador en sí mismo hace simples cálculos simples de tiempo usando time.time() & una agregación muy simple.

¿Los decoradores agregan una sobrecarga significativa a un sistema? No puedo encontrar nada que respalde eso.

+5

La sobrecarga de la decoración en sí es medible, pero no cerca de 2-3x. Esto no tiene en cuenta el comportamiento de decoración, que puede consumir mucho tiempo dependiendo de lo que esté haciendo (actualizaciones de bases de datos, señales de rebote de la luna, etc.). – PaulMcG

+1

+1 para las señales de rebote de la luna –

+0

Del mismo modo, pero reservando +2 para futuros comentarios: "Sincrónico de la señal de la luna-rebote" – Profane

Respuesta

13

La sobrecarga agregada mediante el uso de un decorador debe ser solo una llamada de función extra.

El trabajo que realiza el decorador no es parte de la sobrecarga, ya que su alternativa es agregar el código equivalente al objeto decorado.

Por lo tanto, es posible que la función de decoración tarde el doble en ejecutarse, pero eso se debe a que el decorador está realizando un trabajo importante que lleva más o menos el mismo tiempo que la función no decorada.

+5

Votación hacia arriba para el error tipográfico. – Dolph

5

Lo que es importante saber es que un decorador tiene un efecto simple:

@decorator 
def f(): 
    … 

es el azúcar solo sintáctica para

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

Por lo tanto, si decorador no hace nada, que no tiene cualquier sobrecarga cuando llama a la función decorada (la llamada decorator(f) toma un poco de tiempo, sin embargo), como en

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

Si el decorador hace algo, solo obtendrá el tiempo que el decorador involucre. Esto normalmente incluye una llamada adicional de función (la de la función decorada), como en

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 

Por lo tanto, en sí mismo, la decoración de una función no añade mucho por encima de lo que quiere hacer: la única sobrecarga obvio que usted En principio, eliminar podría ser no llamar al func() en la función decorada sino copiar su código completo, pero la legibilidad del código sufriría (la legibilidad y la flexibilidad son algunas de las razones por las que los decoradores existen en primer lugar).

+0

-1 La sobrecarga de llamada de función en Python no es insignificante. Y sugerir que uno replique el código 'func()' en el decorador derrota el punto total de un decorador en primer lugar. En todo caso, preferiría replicar el código del decorador en 'func()', pero de nuevo, si hacemos eso, la simplicidad de usar el decorador se ve frustrada y el código 'func()' está contaminado con el comportamiento decorativo . Realmente no puede decir "si el decorador no hace nada, no tiene ningún gasto adicional". Los decoradores son útiles para el seguimiento de códigos, etc., pero tienen el costo de una llamada de función adicional en tiempo de ejecución. – PaulMcG

+0

@Paul: Efectivamente, la sobrecarga de llamadas a funciones es relativamente significativa en Python (¡nunca se ha dicho lo contrario!). Y estoy de acuerdo con el hecho de que poner el código 'func()' en el decorador derrota el punto de una decoración (como escribí). ¡Por lo tanto, estamos totalmente de acuerdo! Solo le estaba dando puntos clave que permiten que el póster original comprenda exactamente de dónde proviene la sobrecarga de un decorador. – EOL

+0

Mi principal objeción fue con su declaración "si el decorador no hace nada, no tiene ningún gasto adicional", que sonaba como si estuviera pasando por alto la llamada a la función adicional. Fui a eliminar mi voto negativo, pero SO no me dejará a menos que haga una edición de su respuesta. – PaulMcG

4

¿Los decoradores agregan una sobrecarga significativa a un sistema? No puedo encontrar nada que respalde eso.

Agregan casi ningún gasto mensurable. Cero.

Es importante tener en cuenta que el decorador se ejecuta una vez para crear la función decorada. Una vez.

La función decorada tiene dos partes.

  1. whatever decoration was added. Esto no está por encima.

  2. más la función original. Esto no está por encima.

No hay una sobrecarga real en absoluto. Es posible que, con cierto cuidado, pueda medir la sobrecarga de una función adicional llamada y retorno como parte de una función decorada, pero eso es casi inconmensurablemente pequeño. Y es probablemente mucho menos que un diseño alternativo que no usa decoración.

Cuestiones relacionadas