Killozapit posted a little snippet here.
http://www.rpgmakervxace.net/topic/26685-a-mysterious-optimization-in-yanfly-engine-ace-extra-param-formulas/
I've never thought to use procs like this, but then it became pretty obvious once I saw it.
Basically, the general pattern I use for formula evaluation is this
def eval_my_formula(formula, v=$game_variables, s=$game_switches, ... ) eval(formula)endAnd it works fine. You pass in
And it will return whatever's in variable 2 plus 3.If var2 is 4, then the formula will return 7.
If var2 is 20, then the formula will return 23.
But eval's are expensive. It doesn't matter as much if it's a one-off thing cause it's still pretty fast for most simple formulas, but there are scripts that are constantly eval'ing conditions every other frame and that will be a huge performance hit.
So what if we don't have to do it?
The trick that killozapit shows is to store the formula itself as a lambda. You would need to eval it initially, which is expensive, but after the proc has been created, you just need to re-use it again and again.
So given my simple formula eval method, we can optimize it as follows
def eval_my_formula(formula, v=$game_variables, s=$game_switches, ... ) @myFormulaProc ||= eval("lambda { #{formula} }" ) @myFormulaProc.callendAnd now instead of eval'ing, it just needs to make a method call.After all, the purpose of eval'ing in the first place is to allow users to specify their own formulas without having to go into the code themselves and add it. The formula is essentially a proc, so why not treat it like one?
There are some problems with this implementation at this point, and the biggest one you need to avoid is storing the proc with an instance of any object that you will eventually marshal, cause that will just fail.
Are there any other issues?
http://www.rpgmakervxace.net/topic/26685-a-mysterious-optimization-in-yanfly-engine-ace-extra-param-formulas/
I've never thought to use procs like this, but then it became pretty obvious once I saw it.
Basically, the general pattern I use for formula evaluation is this
def eval_my_formula(formula, v=$game_variables, s=$game_switches, ... ) eval(formula)endAnd it works fine. You pass in
Code:
eval_my_formula("v[2] + 3")
If var2 is 20, then the formula will return 23.
But eval's are expensive. It doesn't matter as much if it's a one-off thing cause it's still pretty fast for most simple formulas, but there are scripts that are constantly eval'ing conditions every other frame and that will be a huge performance hit.
So what if we don't have to do it?
The trick that killozapit shows is to store the formula itself as a lambda. You would need to eval it initially, which is expensive, but after the proc has been created, you just need to re-use it again and again.
So given my simple formula eval method, we can optimize it as follows
def eval_my_formula(formula, v=$game_variables, s=$game_switches, ... ) @myFormulaProc ||= eval("lambda { #{formula} }" ) @myFormulaProc.callendAnd now instead of eval'ing, it just needs to make a method call.After all, the purpose of eval'ing in the first place is to allow users to specify their own formulas without having to go into the code themselves and add it. The formula is essentially a proc, so why not treat it like one?
There are some problems with this implementation at this point, and the biggest one you need to avoid is storing the proc with an instance of any object that you will eventually marshal, cause that will just fail.
Are there any other issues?
Last edited by a moderator:

