Faster Lua VM: Studio beta

Note, we’ve disabled Luau on all games because of a reported bug in repeat…until loops. We will fix this and re-enable the VM in a week or so.

Because the VM is basically almost live we will not enable it on a per-game basis anymore, just wait a bit and it will be live everywhere.

8 Likes

Would it be possible to optimize constant localizations that are made before any code that could possibly use getfenv/setfenv runs? The value of these localizations would be 100% consistent regardless of any potential getfenv/setfenv usage (unless loadstring is being used). The corresponding upvalues could also be removed in the generated code.
Example ModuleScript:

local ipairs = ipairs
local Vector3_new = Vector3.new

_G() -- This statement may change the environment potentially

return function(list)
	for i, v in ipairs(list) do
		list[i] = Vector3_new(v, v, v)
	end
end

Would multi-declarations also be included in future optimizations? My Lua source simplifier combines adjacent declarations in some cases.
Example ModuleScript:

local ipairs, CONSTANT = ipairs, 1
return function(list)
	for i, v in ipairs(list)
		list[i] = v + CONSTANT
	end
end

My setfenv use-case automatically adds an environment-setting statement to the top of ModuleScripts before I publish, so I could easily change this to instead reference data using a global upvalue table. My concern is how this affects function memory usage and creation performance, because most functions in my game would need access to this upvalue.

I’m pretty sure Lua 5.3 implements environments as upvalues, and optimizes access using GETTABUP / SETTABUP opcodes, but in Lua 5.1, a function’s environment field is allocated no matter what, and is thus wasted if I don’t use setfenv. I don’t think Luau can do this optimization if getfenv/setfenv is to be fully supported, unless a function closure can be reallocated to make room for the new unique environment. 8 bytes and an ~11% increase in execution time may seem insignificant, but my game is very Lua-heavy, and the case I’m most worried about is my game’s custom animation system.

My animation system generates optimal function closures for a joint using one out of hundreds of function templates. This makes changing/creating a joint more expensive, but achieves the best possible Lua performance when the resulting closure is called hundreds or thousands of times. Setting part.CFrame is definitely the bottleneck here, but these functions do a fuzzy cframe test so it only sets part.CFrame when the joint’s cframe changes by a position delta or matrix delta.

This is a bit off-topic, but a FuzzyEq / IsClose method for cframes would greatly improve the performance of custom animation systems, because it could be used to efficiently reduce the frequency of part.CFrame assigments:
bool CFrame:FuzzyEq ( CFrame other, number positionEpsilon, number matrixEpsilon )

1 Like

This is really involved - this requires us to make the compiler and VM more complicated for the sake of adding a fragile bypass to fenv deoptimizations. I don’t think this is the right balance of complexity; as mentioned previously, if getfenv/setfenv are still necessary somehow at large, not just in your specific recompilation use-case, we need to find a different way to support that that is guaranteed to not disable optimizations.

All our optimizations around constants/localization should handle multiple assignments as well, as long as the assignments do not require destructuring (e.g something like local a, b = unpack({1, 2}) won’t be optimized but local a, b = 1, 2 will)

I’m not sure but I suspect with the new VM doing this might not be as beneficial as it used to be and you may lose on a large scale (when running many different animations for many different characters) due to the differences in the code you run. IOW I’m not sure this optimization is justified (of course I haven’t profiled your code so you know best)

2 Likes

I know currently reading or writing to getfenv or using setfenv causes some optimizations to not be in effect, could this be changed so only writing to getfenv or using setfenv causes the optimization loss while reading from it is fine?

Is or will newproxy be optimized, and will using it affect any other optimizations?

No plans to optimize newproxy, but no side-effects to using it either.

Thank you so much! I’ve been waiting for this for a long time. :happy2:

Better security too?

1 Like