Faster Lua VM: Studio beta

Will assigning a library’s member to a variable or table cause any issues? I’m currently storing all global functions inside a table to keep my code clean in non-performance critical scripts.

An example:

local global = {abs = math.abs}--will this in any way affect the next line?
local val = math.abs(-5)

Will this increase the speed of events like .touched as well?

1 Like

This update does not affect physics computations. It’s about improving performance of Lua code.

2 Likes

I’m getting an error when using ResetButtonCallback:

image

repro steps: open a baseplate, put a localscript in starterplayerscripts and use ResetButtonCallback:

game.StarterGui:SetCore("ResetButtonCallback", function()
	print "hello!"
end)

This is unrelated to the new VM, I’ll ping the engineer who implemented this.

1 Like

I temporarily disabled this error message locally and ran the code, it produces this output:

17:52:45.916 - ResetButtonCallback must be set to a BindableEvent or a boolean

The change unfortunately causes an error before we can get to this warning message, so when this situation happens it is less clear what actually went wrong.

2 Likes

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”.

3 Likes

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.

2 Likes

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.

4 Likes

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? https://www.roblox.com/games/292439477/Sniper-Update-Phantom-Forces

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 = Instance.new('Part', game.ReplicatedStorage);
	
	game:GetService('Debris'):AddItem(part, 3);
	
	if (tick()-t > 3) then
		print(part);
		wait()
		print(part);
		delay(0, function()
			print(part('aaa'), part);
		end)
		delay(1, function()
			print(part);
		end)
	end
until tick()-t > 3

print('BREAKING')

Output:

image

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.

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