lua-users home
lua-l archive

Re: Issues with the current varargs implementation (Was: Re: inadequate documentation for select and table.unpack)

[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)

AltStyle によって変換されたページ (->オリジナル) /