Faster Lua VM: Studio beta

I’d love to see games push this new VM to its limit.

1 Like

In the new Lua vm.
This way of calling a method in a Instance: Instance( method name )
How I used the method: game(“GetService”, “Players”)

Basically, another wall to call a method, but with more control and freedom.
Sadly, this was broken. Instead of the method doing what it is suppose to do. It errors.

attempt to call a userdata value

So, can we keep this feature. So that we don’t have to use loadstring or some other hidden methods of calling a method in Instance. Thanks!

I don’t think you have read the thread correctly. This wasn’t a feature at all it was a accidental result with their old __namecall.

I don’t believe they are going to be keeping it since it was purely accidental but who knows.

The way you propose is worlds hackier than proper solutions. I assume you mean dynamically calling methods (for whatever use case).

Try doing instance[method_name](instance, params...).
Like GetGlobals said, it was an accidental “feature”.


Thanks! I never knew that existed. Been looking around for an alternative.

Is there any way an exception could be made for things like getfenv(2).script? I believe that is by far the most common form of using getfenv or setfenv and in my opinion the most acceptable. The optimizations could be applied to a lot more existing code if getfenv(number).script didn’t disable the optimizations.


Approximate time for one cycle on my RTS (identical conditions):

  • Pre-Luau: 0.0021 seconds
  • Luau V1: 0.0007-0.0009 seconds
  • Luau V2 (current): 0.0011-0.0013 seconds

It seems like V1 to V2 slowed down significantly for me, sadly. Still, it’s a massive improvement compared to before!

1 Like

What do you mean by V1? I don’t think there were any changes that could reduce performance.

Also, if you can share your script(s) with me privately we can take a look and see what we can improve further.


When production test run, take 2 was enabled, I noticed it was slower than before despite no changes on my part.

I’ll message you regarding sharing my scripts.

Hello, I forgot to ask at lunch yesterday, could the new Luau VM be enabled on the main Phantom Forces place?

All seems good in the test place.

Luau is currently enabled on all games.

See: Faster Lua VM: Production test run, take 2

Currently getting some odd results with the following code:

local t = tick();
repeat wait()
	local part ='Part', game.ReplicatedStorage);
	game:GetService('Debris'):AddItem(part, 3);
	if (tick()-t > 3) then
		delay(0, function()
			print(part('aaa'), part);
		delay(1, function()
until tick()-t > 3




Issue only occurs in Luau.

1 Like

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.


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 =

_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)

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

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)


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