LuaU Math Operations Performance

Hi DevForumers, a while ago I had a question: Even if it’s a thousandth better, does performing mathematical operations on hexadecimal result in better performance than using decimal?

I tried out this question in mind with a little benchmark test, inputted below.

local timeNow = tick() 
local hexNumber = 0x1F04864B + 0x1F04864B 
print(hexNumber) 

warn(tick()-timeNow) --> 0.00006413459777832031

local _TimeNow = tick()
local Number = 520390219 + 520390219 
print(Number)

warn(tick()-_TimeNow) --> 0.000022172927856445312

I was rather confused by the results, expecting operations on hexadecimal to result in shorter times than that of operations on decimal… IIRC the results elsewhere concluded that hexadecimal was faster than decimal, though with binary being the fastest.

Was the source I read false or is LuaU different in some way? Why is it that hexadecimal is slower than decimal?

Ciao, Calamixy

When you run performance tests like these it’s a good idea to do many of them, since the amount of time it takes to do a basic arithmetic operation is tiny.

On the machine level, there is no difference between a number that is defined in decimal or hexadecimal. The only time difference might theoretically come from how long it may take the compiler/interpreter to translate a number to machine code depending on whether it was defined in decimal or hex.

The code I used:
local n = 1000000 -- number of tests

wait(5) -- let other roblox scripts start up

local t = 0
for i = 1, n do
	if (i % 10000 == 0) then wait() end
	local now = tick()
	local test = 0x1F04864B + 0x1F04864B
	t = t + tick() - now
end

print("hex add:", t / n)

t = 0
for i = 1, n do
	if (i % 10000 == 0) then wait() end
	local now = tick()
	local test = 520390219 + 520390219
	t = t + tick() - now
end

print("dec add:", t / n)

t = 0
for i = 1, n do
	if (i % 10000 == 0) then wait() end
	local now = tick()
	local test = 0x1F04864B * 0x1F04864B
	t = t + tick() - now
end

print("hex mult:", t / n)

t = 0
for i = 1, n do
	if (i % 10000 == 0) then wait() end
	local now = tick()
	local test = 520390219 * 520390219
	t = t + tick() - now
end

print("dec mult:", t / n)

t = 0
for i = 1, n do
	if (i % 10000 == 0) then wait() end
	local now = tick()
	local test = 0x1F04864B / 0x1F04864B
	t = t + tick() - now
end

print("hex div:", t / n)

t = 0
for i = 1, n do
	if (i % 10000 == 0) then wait() end
	local now = tick()
	local test = 520390219 / 520390219
	t = t + tick() - now
end

print("dec div:", t / n)

The results:

hex add: 2.8787612915039063e-08
dec add: 2.8634309768676758e-08
hex mult: 2.8858184814453124e-08
dec mult: 2.8642654418945314e-08
hex div: 2.8728961944580077e-08
dec div: 2.8785228729248045e-08

It doesn’t appear very conclusive. The differences start after the ninth decimal place, which is miniscule, and can lean either way.

2 Likes

Because the hexadecimal result is being translated into its decimal equivalent.

2 Likes

Really interesting, thank you for both your tips on benchmarking as well as the solution! I had assumed previously that hexadecimal was a quicker translation process into machine code than decimal, though, I still have a question. On a video, it used hexadecimal (0x5f3759df) for a number (1597463007) and performed various operations on it. I was wondering why this was so and why the author didn’t use the value in decimal to do such with it. Is there a valid reason behind this, or is it by preference?

It was most likely by preference. Some programmers when using huge magic numbers in their code like to write it in hexadecimal.

if you’re doing advanced operations like bit shifts, bit masks and bit operations then it makes total sense to use hexadecimal or binary values. Also in lower level languages, using numbers that powers of 2 like 2, 4, 8, 16, 1024, 8096… is faster and more accurate since dividing by those numbers is really simple, is just shifting some bits around.
But all of this crazy optimizations and stuff doesn’t apply to our modern days of programming especially for modern languages and even more for interpreted (scripting) languages.
When you’re using a interpreted language like Lua and Python, Don’t even try such minimal optimizations since a lot of times it just results in the opposite effect.
hexadecimal numbers is really related to binary, but programmers prefer hexadecimal values since it’s more concise and easier to read and reason about.
for example
Dec( 255 ) = Hex( FF ) = Bin( 11111111 )
where every F in hex basically represents 1111 in binary
so one character to represent 4 bits is really powerful

2 Likes