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: 234
Joined: Mon Aug 29, 2016 8:51 am

math.random > love.math.random

Post by KayleMaster »

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.
User avatar
Nixola
Inner party member
Posts: 1949
Joined: Tue Dec 06, 2011 7:11 pm
Location: Italy

Re: math.random > love.math.random

Post by Nixola »

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
lt = love.thread
li = love.image
lg = love.graphics
KayleMaster
Party member
Posts: 234
Joined: Mon Aug 29, 2016 8:51 am

Re: math.random > love.math.random

Post by KayleMaster »

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 ).
User avatar
0x25a0
Prole
Posts: 36
Joined: Mon Mar 20, 2017 10:08 pm
Contact:

Re: math.random > love.math.random

Post by 0x25a0 »

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 :)
User avatar
Nixola
Inner party member
Posts: 1949
Joined: Tue Dec 06, 2011 7:11 pm
Location: Italy

Re: math.random > love.math.random

Post by Nixola »

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
lt = love.thread
li = love.image
lg = love.graphics
User avatar
zorg
Party member
Posts: 3436
Joined: Thu Dec 13, 2012 2:55 pm
Location: Absurdistan, Hungary
Contact:

Re: math.random > love.math.random

Post by zorg »

It's better though, Löve's implementation, i mean.
Me and my stuff :3True 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.
User avatar
Nixola
Inner party member
Posts: 1949
Joined: Tue Dec 06, 2011 7:11 pm
Location: Italy

Re: math.random > love.math.random

Post by Nixola »

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
lt = love.thread
li = love.image
lg = love.graphics
User avatar
erasio
Party member
Posts: 118
Joined: Wed Mar 15, 2017 8:52 am
Location: Germany

Re: math.random > love.math.random

Post by erasio »

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: 234
Joined: Mon Aug 29, 2016 8:51 am

Re: math.random > love.math.random

Post by KayleMaster »

Yeah but I just need random tile gen (different shades) so it'd do fine for me.
User avatar
vrld
Party member
Posts: 917
Joined: Sun Apr 04, 2010 9:14 pm
Location: Germany
Contact:

Re: math.random > love.math.random

Post by vrld »

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
Post Reply

Who is online

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