Помещает ли функция внутри другой функции в lua повышение производительности в lua? - PullRequest
1 голос
/ 25 марта 2020

Если я помещу функцию в другую функцию, чтобы вызвать ее в функцию, которую мы добавили внутри функции, как в следующем примере:

local function readInputFromUser() 
    local doSum()
        print("Give me a number")
        return io.read("n")
    end
    num1 = doSum()
    num2 = doSum()
    print("The sum of " num1 .. " and " .. num2 .. " is equaling " num1 + num2)
end

Придаст ли это моей программе повышение производительности по сравнению с вызовом функция, инициированная как в следующем примере:

local doSum()
    print("Give me a number")
    return io.read("n")
end

local function readInputFromUser() 
    num1 = doSum()
    num2 = doSum()
    print("The sum of " num1 .. " and " .. num2 .. " is " num1 + num2)
end

Было бы также полезно поместить функцию doSum () во втором примере в качестве глобальной функции для исполнения?

1 Ответ

2 голосов
/ 25 марта 2020

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

Посмотрите на байт-код LuaJIT первого кода:

Это байт-код функции doSum:

0001    GGET     0   0      ; "print"
0002    KSTR     1   1      ; "Give me a number"
0003    CALL     0   1   2
0004    GGET     0   2      ; "io"
0005    TGETS    0   0   3  ; "read"
0006    KSTR     1   4      ; "n"
0007    CALLT    0   2

Это начало функции readInputFromUser:

0001    FNEW     0   0
0002    MOV      1   0
0003    CALL     1   2   1
...
...
...

Посмотрите на первую инструкцию:

0001 FNEW 0 0

FNEW означает Create new closure from prototype D and store it in A.

Эта инструкция создаст новое закрытие при каждом запуске readInputFromUser (Закрытие - это функция внутри функции). Создание замыкания содержит несколько процедур. Он выделяет пространство для новой функции, добавляет в список G C, добавляет значения, локальные и многие другие вещи.

Это стоит времени ЦП, а также нарушает компиляцию JIT. (В простом Lua процессорное время для замыканий больше)

Ваша функция doSum не использует никаких значений из readInputFromUser, поэтому вместо этого вы можете создать doSum снаружи readInputFromUser и используйте его как значение upvalue (значение Upvalue является локальной переменной вне (и выше) функции). Upvalues ​​стоит дороже, чем локальные, но создание замыкания стоит намного дороже, так что здесь можно использовать upvalue. Вы можете избежать этого повышения, сделав doSum глобальным, но глобальные стоят немного больше (locals > upvalues > globals > closures).

Сумма : Создание замыкания стоит дорого, если ваша функция не ' t использовать значения upval, вы можете создать его один раз снаружи и использовать повторно.

Кстати, у вас есть синтаксические ошибки в последнем print и в doSum определении. Кроме того, это приблизительный тест теста между первым кодом и вторым:

doSum inside readInputFromUser: 0.29265 (Min: 0.27215, Max: 0.35823, Average: 0.29573) second(s) (81816.93%) (818 times slower)
doSum as upvalue: 0.00036 (Min: 0.0003, Max: 0.00108, Average: 0.00042) second(s) (100%)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...