## math.random > love.math.random

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
KayleMaster
Party member
Posts: 212
Joined: Mon Aug 29, 2016 8:51 am

### math.random > love.math.random

I did some test while optimizing a problematic loop and these are my findings:
2621440 tests
math.random ~25ms
love.math.random ~35 ms
Is this because of the extra access table (love.) ?
Just something interesting I found.

Nixola
Inner party member
Posts: 1940
Joined: Tue Dec 06, 2011 7:11 pm
Location: Italy

### Re: math.random > love.math.random

It may be, although a 40% increase in time looks excessive. Can you try making both functions local when testing?
lf = love.filesystem
ls = love.sound
la = love.audio
lp = love.physics
li = love.image
lg = love.graphics

KayleMaster
Party member
Posts: 212
Joined: Mon Aug 29, 2016 8:51 am

### Re: math.random > love.math.random

They are both local, in fact, it's just one function, I just change math.random to love.math.random in the function and compile again. Did this 10 times and got consistent results.
Anyways, it's not that noticeable, and no, It wasn't the problem of my loop ( I wish it was ).

0x25a0
Prole
Posts: 36
Joined: Mon Mar 20, 2017 10:08 pm
Contact:

### Re: math.random > love.math.random

As far as I know the pseudo-random number generator in LOVE is not based on Lua's PRNG. So, the performance difference is not because of an extra table access, it's because they are inherently different PRNGs

Nixola
Inner party member
Posts: 1940
Joined: Tue Dec 06, 2011 7:11 pm
Location: Italy

### Re: math.random > love.math.random

Yeah, LÖVE's is indeed slower. I just thought it was faster for some reason.
lf = love.filesystem
ls = love.sound
la = love.audio
lp = love.physics
li = love.image
lg = love.graphics

zorg
Party member
Posts: 2732
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

### Re: math.random > love.math.random

It's better though, Löve's implementation, i mean.
Me and my stuff True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.

Nixola
Inner party member
Posts: 1940
Joined: Tue Dec 06, 2011 7:11 pm
Location: Italy

### Re: math.random > love.math.random

Yeah, that's a given; it's also consistent across all platforms and Lua interpreters (while LuaJIT packs a consistent PRNG, LÖVE can also use standard Lua).
lf = love.filesystem
ls = love.sound
la = love.audio
lp = love.physics
li = love.image
lg = love.graphics

erasio
Party member
Posts: 118
Joined: Wed Mar 15, 2017 8:52 am
Location: Germany

### Re: math.random > love.math.random

Plus a larger period and actual randomness without staying by setting a seed and calling random 3 times.

I mean math.random is just weird. Functional when you follow the docs. But I wouldn't recommend using it.

Plus love has random generator objects allowing you to have random generators assigned to parts of your game for actually consistent seed based randomness.

Instead of just having one which may play into combat, map generation and more meaning the order of random calls will affect the result and make debugging a pain.

KayleMaster
Party member
Posts: 212
Joined: Mon Aug 29, 2016 8:51 am

### Re: math.random > love.math.random

Yeah but I just need random tile gen (different shades) so it'd do fine for me.

vrld
Party member
Posts: 917
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany
Contact:

### Re: math.random > love.math.random

I was curious, so I did my own test. I also computed the variation in run time to get a sense if the difference is (statistically) significant. This is the code I used:

Code: Select all

-- compute mean and standard deviation from sample
local function mean_std(t)
assert(#t >= 2)
local mean, scatter = 0, 0
for n,x in ipairs(t) do
local d = x - mean
mean = mean + d/n
scatter = scatter + d * (x - mean)
end
return mean, math.sqrt(scatter / (#t - 1))
end

-- take N samples of K runs of f().
local function profile(f, N, K)
local t = {}
for n = 1,N or 10000 do
local t0 = love.timer.getTime()
for k = 1,K or 100 do
f()
end
t[#t+1] = (love.timer.getTime() - t0) / (K or 100)
end
return t
end

-- first run to warm up the JIT compiler
mean_std(profile(math.random))
mean_std(profile(love.math.random))

-- actual measurement run
m1,s1 = mean_std(profile(math.random), 1000000, 10000)
m2,s2 = mean_std(profile(love.math.random), 1000000, 10000)

local ns = 1e9 -- one second is 1000000000 nanoseconds
print("libc:", ("%.3f ns ± %.3f ns"):format(m1*ns, s1*ns))
print("love:", ("%.3f ns ± %.3f ns"):format(m2*ns, s2*ns))

love.event.quit()
And this is one result (you may get other numbers, even across runs):

Code: Select all

libc:	8.958 ns ± 2.154 ns
love:	14.195 ns ± 2.300 ns
What does that tell us? Well, your numbers are most probably correct: 2621440 runs take, on average, 25ms for math.random() or 35ms for love.math.random(). The difference also seems to be significant.
But: One evaluation of either function takes less than 20 nanoseconds. Nanoseconds! Given the benefits of love's PRNG (that is: consistency over OSes and better statistical properties), it seems as if this is not the right place to start optimizing your code.
I have come here to chew bubblegum and kick ass... and I'm all out of bubblegum.

hump | HC | SUIT | moonshine

### Who is online

Users browsing this forum: Bing [Bot], Google [Bot] and 7 guests