2011-05-22 9 views
8

Para una función dentro de otra función, ¿Lua "instancia" la función interna en cada llamada a la función externa? Si es así, ¿bar() en el siguiente código tiene un rendimiento peor que foo()?Función interna de Lua frente a la función de nivel de módulo

local function a() 
    print 'a' 
end 

function foo() 
    a() 
end 

function bar() 
    function b() 
    print 'b' 
    end 

    b() 
end 

Respuesta

15

caso de prueba 1: a y b vez global, sin incrustación.

$ cat junk.lua ; time lua junk.lua 
function a(n) 
    return n + 1 
end 

function b(n) 
    return a(n) 
end 

for c = 1, 10000000 do 
    b(c) 
end 


real 0m1.743s 
user 0m1.740s 
sys 0m0.000s 

hora Usuario: 1.74s.

Caso de prueba 2: a local, b global, sin incrustaciones.

local function a(n) 
    return n + 1 
end 

function b(n) 
    return a(n) 
end 

for c = 1, 10000000 do 
    b(c) 
end 


real 0m1.388s 
user 0m1.390s 
sys 0m0.000s 

hora Usuario 1.39s.

Caso de prueba 3: a y b ambos locales, sin incrustaciones.

$ cat junk.lua ; time lua junk.lua 
local function a(n) 
    return n + 1 
end 

local function b(n) 
    return a(n) 
end 

for c = 1, 10000000 do 
    b(c) 
end 


real 0m1.194s 
user 0m1.200s 
sys 0m0.000s 

hora Usuario 1.2s.

Caso de prueba 4: a integrado en b, a global, b local.

$ cat junk.lua ; time lua junk.lua 
local function b(n) 
    function a(n) 
     return n + 1 
    end 

    return a(n) 
end 

for c = 1, 10000000 do 
    b(c) 
end 


real 0m2.804s 
user 0m2.790s 
sys 0m0.000s 

hora Usuario: 2.79s. (!)

Caso de prueba 5: a incrustado en b, ambos locales.

$ cat junk.lua ; time lua junk.lua 
local function b(n) 
    local function a(n) 
     return n + 1 
    end 

    return a(n) 
end 

for c = 1, 10000000 do 
    b(c) 
end 


real 0m2.540s 
user 0m2.530s 
sys 0m0.000s 

hora Usuario: 2.53s.

Resumen Resultado:

  1. Es fácil escribir pruebas para confirmar o negar intuiciones sobre el rendimiento. Probablemente deberías hacer esto en lugar de confiar en la respuesta de crowd-sourcing. (La multitud a menudo está equivocada, verá).
  2. La creación de funciones locales en lugar de globales tiene un impacto positivo significativo en la sobrecarga de llamadas de función. (Aproximadamente un 30% mejor en este conjunto de casos de prueba cuando ambas funciones eran locales.)
  3. La incorporación de una función en otra función tiene un grave impacto negativo en la sobrecarga de la llamada a la función. (Aproximadamente 110% peor en este conjunto de casos de prueba cuando ambas funciones eran locales.)
  4. ¿Mencioné que las pruebas son probablemente una buena idea en lugar de confiar en la multitud?
+1

¡Gracias! Lo habría probado, pero no estaba seguro de cómo. Supongo que debería haber sido mi primera pregunta. – johncage

5

bar será más lento debido a que está creando un nuevo objeto de la función cada vez. Si desea declarar funciones dentro de una función, probablemente desee devolver una clausura.

local bar = function() 
    local f = function() 
    -- Lots of stuff... 
    end 
    local g = function() 
    -- Also lots of stuff 
    end 
    return function() 
    -- Do something with f and g... 
    end 
end 

local created_f = bar() 
created_f() 
created_f() -- Now you can skip the function initialization. 
+0

Me ganaste porque lo hice de la manera sin pretensiones. : D +1 –

+0

De hecho, hice un poco de benchmarking para verificar algunas cosas, pero me di cuenta de que el póster original probablemente debería hacerlo él mismo (como dijiste en tu respuesta). +1 para ti también para una respuesta detallada. – ponzao

+0

Ojalá pudiera darle otro +1 por el código y que muestre cómo usar los cierres. (También me gustaría haber pensado en mostrar el uso del cierre yo mismo.) –

Cuestiones relacionadas