From 12a449abec299f54a1b8aa2b7e37e88771611769 Mon Sep 17 00:00:00 2001 From: Lobby Date: Tue, 1 Sep 2020 10:38:36 +0200 Subject: [PATCH] Reduce allocations per LuaClosure call Every call of a LuaClosure issues creation of a new stack frame for the function execution. Since this stack is usually thrown away after execution pooling them can help to reduce garbage collection overhead (there's one exception to this: the stack can be used as part of the returned varargs object, in that case it cannot be reused since that could cause conflicts). In my use case this change was a useful for calling a lot of Lua functions on a mobile device. --- src/core/org/luaj/vm2/LuaClosure.java | 85 +++++++++++++++++++++++---- 1 file changed, 73 insertions(+), 12 deletions(-) diff --git a/src/core/org/luaj/vm2/LuaClosure.java b/src/core/org/luaj/vm2/LuaClosure.java index 46a3556f..a2a0658a 100644 --- a/src/core/org/luaj/vm2/LuaClosure.java +++ b/src/core/org/luaj/vm2/LuaClosure.java @@ -23,6 +23,9 @@ package org.luaj.vm2; import org.luaj.vm2.lib.DebugLib.CallFrame; +import java.util.ArrayList; +import java.util.List; + /** * Extension of {@link LuaFunction} which executes lua bytecode. *

@@ -128,44 +131,98 @@ public class LuaClosure extends LuaFunction { public String tojstring() { return "function: " + p.toString(); } - + + + private List stackPool = new ArrayList<>(); private LuaValue[] getNewStack() { + if (stackPool.isEmpty()) { + return getNewStackRaw(); + } else { + return stackPool.remove(stackPool.size() - 1); + } + } + + private LuaValue[] getNewStackRaw() { int max = p.maxstacksize; LuaValue[] stack = new LuaValue[max]; System.arraycopy(NILS, 0, stack, 0, max); return stack; } + + private void releaseStack(LuaValue[] stack) { + System.arraycopy(NILS, 0, stack, 0, stack.length); + stackPool.add(stack); + } public final LuaValue call() { LuaValue[] stack = getNewStack(); - return execute(stack,NONE).arg1(); + LuaValue result = execute(stack,NONE).arg1(); + releaseStack(stack); + return result; } public final LuaValue call(LuaValue arg) { LuaValue[] stack = getNewStack(); + LuaValue result; switch ( p.numparams ) { - default: stack[0]=arg; return execute(stack,NONE).arg1(); - case 0: return execute(stack,arg).arg1(); + default: + stack[0]=arg; + result = execute(stack,NONE).arg1(); + break; + case 0: + result = execute(stack,arg).arg1(); + break; } + releaseStack(stack); + return result; } public final LuaValue call(LuaValue arg1, LuaValue arg2) { LuaValue[] stack = getNewStack(); + LuaValue result; switch ( p.numparams ) { - default: stack[0]=arg1; stack[1]=arg2; return execute(stack,NONE).arg1(); - case 1: stack[0]=arg1; return execute(stack,arg2).arg1(); - case 0: return execute(stack,p.is_vararg!=0? varargsOf(arg1,arg2): NONE).arg1(); + default: + stack[0]=arg1; + stack[1]=arg2; + result = execute(stack,NONE).arg1(); + break; + case 1: + stack[0]=arg1; + result = execute(stack,arg2).arg1(); + break; + case 0: + result = execute(stack,p.is_vararg!=0 ? varargsOf(arg1,arg2) : NONE).arg1(); + break; } + releaseStack(stack); + return result; } public final LuaValue call(LuaValue arg1, LuaValue arg2, LuaValue arg3) { LuaValue[] stack = getNewStack(); + LuaValue result; switch ( p.numparams ) { - default: stack[0]=arg1; stack[1]=arg2; stack[2]=arg3; return execute(stack,NONE).arg1(); - case 2: stack[0]=arg1; stack[1]=arg2; return execute(stack,arg3).arg1(); - case 1: stack[0]=arg1; return execute(stack,p.is_vararg!=0? varargsOf(arg2,arg3): NONE).arg1(); - case 0: return execute(stack,p.is_vararg!=0? varargsOf(arg1,arg2,arg3): NONE).arg1(); + default: + stack[0]=arg1; + stack[1]=arg2; + stack[2]=arg3; + result = execute(stack,NONE).arg1(); + break; + case 2: + stack[0]=arg1; + stack[1]=arg2; + result = execute(stack,arg3).arg1(); + break; + case 1: + stack[0]=arg1; + result = execute(stack,p.is_vararg!=0 ? varargsOf(arg2,arg3) : NONE).arg1(); + break; + case 0: + result = execute(stack,p.is_vararg!=0 ? varargsOf(arg1,arg2,arg3) : NONE).arg1(); + break; } + releaseStack(stack); + return result; } public final Varargs invoke(Varargs varargs) { @@ -176,7 +233,11 @@ public class LuaClosure extends LuaFunction { LuaValue[] stack = getNewStack(); for ( int i=0; i