lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


On 6/22/2016 9:25 PM, Dirk Laurie wrote:
2016-06-22 15:16 GMT+02:00 KHMan <keinhong@gmail.com>:
On 6/22/2016 8:39 PM, Dirk Laurie wrote:

2016-06-22 12:21 GMT+02:00 steve donovan:

On Tue, Jun 21, 2016 at 10:47 PM, Philipp Janda:

First of all: vararg performance is fine. .... Performance of `select`
is fine too.
Calling it means pushing all of its arguments to the Lua stack -- like
for any
other function.


I also wonder whether we're going to squeeze much more performance out
of this lemon, and whether this is in fact an important lemon.


It is unimportant in the sense that whether traversing the vararg
using select is O(n) or O(n²) seldom matters in practice.

It is important in the sense that it is highly instructive to ponder
the issues involved.

[snip snip]

Hmmm... anyone got an artificial benchmark to test and compare timings? I
don't believe I've seen any timing data so far...

~~~ {benchmark.lua}
function f(...)
   local function g(...)
     return select('#',...)
   end
   local t={}
   for k=1,select('#',...) do
     t[k]=g(select(k,...))
   end
   return t
end

n=tonumber(arg[1])
print(#f(string.byte(("1"):rep(n),1,-1)))
~~~~

…/tmp$ time lua xxx.lua 10000
10000

real    0m0.315s
user    0m0.311s
sys    0m0.004s
…/tmp$ time lua xxx.lua 50000
50000

real    0m9.695s
user    0m9.679s
sys    0m0.004s
…/tmp$

Attached is some extended data. I added an outer loop and ran tests for about 30 seconds. Of course, take benchmarks with a lot of salt...

Adding a "local select = select" makes the thing run maybe 6% faster. I also added a roughly equivalent table passing version. If using an "n" field in the table, the 10,000 size per round is about 14% slower.

--
Cheers,
Kein-Hong Man (esq.)
Kuala Lumpur, Malaysia

Lua 5.3.3 (default make) MinGW/gcc 4.8.1

bench_vararg2.lua

vararg size     outerloop       total time      per round (usec)
================================================================
    10          10000000        30.372              3.0
    50           2000000        32.846             16.4
   100            750000        33.062             44.1
   200            250000        34.213            137
   500             50000        35.718            714
  1000             10000        27.597           2760
  2000              2500        28.765          11506
  5000               500        35.730          71460

bench_vararg2.lua

vararg size     outerloop       total time      per round (sec)
===============================================================
 10000               100        29.628           0.29628
 20000                25        30.622           1.22488
 50000                 5        38.225           7.64500
100000                 1        30.785          30.78500

bench_vararg3.lua (table passing)

table size      outerloop       total time      per round (usec)
================================================================
    10          10000000        24.902              2.5
   100           2500000        29.800             11.9
  1000            250000        24.962             99.8
 10000             25000        27.175           1087
100000              2500        29.870          11948

usec = microsecond
--
-- Dirk Laurie's vararg benchmark 2016-06-22
-- * added a loop for longer runs
--
local select = select

function f(...)
  local function g(...)
    return select('#', ...)
  end
  local t = {}
  for k = 1, select('#', ...) do
    t[k] = g(select(k, ...))
  end
  return t
end

-- 1st argument sets vararg size
-- 2nd argument is for outer loop
if (#arg == 0 or #arg > 2) then
  print("*** run with 1-2 args\n(1) vararg size\n(2) outer loop (default=1)\n")
  return
end
local n = tonumber(arg[1])
local m = tonumber(arg[2] or 1)
local total = 0

for p = 1, m do
  total = total + #f(string.byte(("1"):rep(n), 1, -1))
end
print(total)
--
-- Dirk Laurie's vararg benchmark 2016-06-22
-- * table passing, roughly equivalent
--
function f(d)
  local function g(e, i)
    return #e - i + 1
  end
  local t = {}
  for k = 1, #d do
    t[k] = g(d, k)
  end
  return t
end

-- 1st argument sets vararg size
-- 2nd argument is for outer loop
if (#arg == 0 or #arg > 2) then
  print("*** run with 1-2 args\n(1) vararg size\n(2) outer loop (default=1)\n")
  return
end
local n = tonumber(arg[1])
local m = tonumber(arg[2] or 1)
local total = 0

for p = 1, m do
  total = total + #f{string.byte(("1"):rep(n), 1, -1)}
end
print(total)