Code speed inconsistency

Run this snippit in a Script, and then run it again in a plugin or the command bar.

local t = tick()
for i = 1, 100000 do
end
print((tick() - t)*1000, 'ms')

Results:

  • Plugin: 0.29 ms
  • Script: 4.0 ms

So, unprivileged code is a bit more than an order of magnitude slower than privileged code in this particular benchmark.

The expected behavior is that Lua code runs at a consistent speed across different security contexts.

10 Likes

Can confirm.

I thought maybe adding a wait(5) at the beginning would help to wait for any startup overhead, but no difference was found. Even tried localizing tick to see if it had to do with global lookup; still no difference. Did some other tricks too just to try and verify it.

Would be cool to hear from someone at Roblox as to why this is the case.

I wonder what performance you get on a live server?

Similar results here

I had a Raspberry Pi server running, so I ran this against Lua and LuaJIT, and interestingly found similar time differences. On Lua, it got around 4-5ms; on LuaJIT, it hit around 0.8ms on average.

Although worth noting that Lua is 5.1.5 and LuaJIT is 2.0.3 running Lua 5.1 on my RPi.

There was an earlier thread (can’t find it) where we figured that Roblox added something along the lines of this to the main interpreter loop:

lua_getglobal(L, "script");

I’m thinking that that might be the cause?

How’d you benchmark that?

Does it? Maybe it does. I just ran the same code as posted here, except used os.clock instead of tick.

Here’s the link to the previous thread:

Still don’t think anyone (except some mysterious unknown roblox employee) knows why it happens.

My best guess is that this is due to a debugger hook (Studio-only). We have tried previously to limit the damage the debugger does to performance in Studio but it looks like we can go further. Ping @Silent137

edit: and yeah, debugger does getglobal(“script”) I believe. Also something to improve.

4 Likes

But this also happens on the client (as there is/was an exploit that made use of that a few weeks ago, although I didn’t check it since then)

If this is happening on the client doesn’t this mean games are running quite a bit slower then they should be?

This has been happening for a very long time, maybe before the devforums even existed. Games aren’t running slower than “they should be”, just slower than is possible. “Fixing” this would just mean games suddenly run faster (the Lua part at least)

Yeah, t’was what I meant. If this is the case I feel this would be critical to fix (if it can be) as soon as possible considering the magnitude of the speed increase.

Seems like this is the case on the client to a less significant effect, not the server though:

0.0065567493438721 -- Command bar
0.0544290542602544 -- Script ( Studio )
0.0058250427246094 -- Script ( Server )
0.026801824569702-- LocalScript ( Client ), not sure why this number is printed with one less digit (dev console bug?)

Or the server just runs faster in general. I’ve once “benchmarked” a bit of code on my client and the server, and the server ran at least 4x faster. You need to actually check if the script variable gets indexed, which happens/happened (as that exploit made use of it and worked on the server and client)

setfenv(function()end,setmetatable({},{__index=print}))()

Doesn’t print on either client or server, although I noticed the client and server actually run about as fast as each other (~0.007 - ~0.01), occasionally though the client will run slower ( up to ~0.02 ), probably due to background tasks / etc?

fwiw, tostring trims trailing zeros

You might need some code in the function’s body for that to work, as the __indexing apparently happens after each instruction.

Gotcha, forgot about that

It prints in studio so don’t think that’s the problem

1 Like

Ran this on server online using Developer Console:


setfenv(function() print"k" end,setmetatable({},{__index=print}))()
table: 0D568870 script
table: 0D568870 print
table: 0D568870 script
console:3: attempt to call global 'print' (a nil value)
table: 0D568870 script
2 Likes

Just tried with local/scripts, does print. Seems like it does need a body in the function for it to print online but not in studio.

I think I’ve mentioned this somewhere before, although it might be another thread: the __index happens (more or less) every instruction, so if there’s no body, there are no instructions (except RETURN, which doesn’t trigger this it seems)

It happening in studio might be that RETURN, or that getglobal("script") from the debugger that zeuxcg mentioned.