lua-users home
lua-l archive

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


Am 23.06.2016 um 11:53 schröbte Viacheslav Usov:
On Thu, Jun 23, 2016 at 11:30 AM, Dirk Laurie <dirk.laurie@gmail.com> wrote:

It is in fact slightly faster with this example to use a variadic
function (perhaps because the table is local at a shallower level?), but
not very much.

So for n > 9, there is no reason to prefer select over {...}.

No performance reason at least. One advantage of `select` is that you can preallocate stack space so that the iteration itself won't allocate memory and thus can't raise an error. But this only matters if you are really paranoid about your deterministic cleanup (there was a thread a while ago).


The moment that you put an upper bound on n, there is no more any
theoretical distinction between O(1), O(n) and O(n²).

In practical computer science, there is ALWAYS an upper bound. Just like
the tests so far ALL had it.

If the upper bound is small enough (and I'd say in this case that
anything less than LUA_MINSTACK qualifies on that score), there is no
practical distinction either.

I'd say we should just see the facts, the whole nine of them :)

I have attached another micro benchmark for iterating varargs. It appears that the break-even point is around 4 arguments in `...` (which is sooner than I expected):

Lua 5.2, N: 1000000
select #: 0  time: 0.106569 secs
{...}  #: 0  time: 0.121158 secs
select #: 1  time: 0.122787 secs
{...}  #: 1  time: 0.190752 secs
select #: 2  time: 0.161029 secs
{...}  #: 2  time: 0.215188 secs
select #: 3  time: 0.227528 secs
{...}  #: 3  time: 0.244925 secs
select #: 4  time: 0.283881 secs
{...}  #: 4  time: 0.283572 secs
select #: 5  time: 0.322693 secs
{...}  #: 5  time: 0.290039 secs
select #: 6  time: 0.392189 secs
{...}  #: 6  time: 0.317025 secs
select #: 7  time: 0.437019 secs
{...}  #: 7  time: 0.35054 secs
select #: 8  time: 0.496888 secs
{...}  #: 8  time: 0.387774 secs
select #: 16  time: 1.017306 secs
{...}  #: 16  time: 0.583985 secs
select #: 32  time: 2.523032 secs
{...}  #: 32  time: 0.970641 secs
select #: 64  time: 7.447786 secs
{...}  #: 64  time: 1.812242 secs



Cheers,
V.


Philipp


#!/usr/bin/lua

local N = tonumber( arg[ 1 ] ) or 1000000
local M = tonumber( arg[ 2 ] ) or 100
local M2 = 8
local do_collect = true
local os_clock = os.clock
local select = select
local collectgarbage = collectgarbage
local unpack = table.unpack or unpack


local function noop( ... ) end

local function bench( n, f, ... )
  local start = os_clock()
  for i = 1, n do
    f( ... )
  end
  if do_collect then collectgarbage() end
  local stop = os_clock()
  for i = 1, n do noop( ... ) end
  if do_collect then collectgarbage() end
  local stop2 = os_clock()
  io.write( "time: ", stop-start-(stop2-stop), " secs\n" )
end

local function with_select( ... )
  for i = 1, select( '#', ... ) do
    local v = select( i, ... )
  end
end

local function with_table( ... )
  local t = { ... }
  for i = 1,#t do
    local v = t[ i ]
  end
end


local n = 0
io.write( _VERSION, ", N: ", N, "\n" )
while n < M do
  local t = {}
  for i = 1,n do t[ i ] = 1 end
  io.write( "select #: ", n, "  " )
  collectgarbage()
  bench( N, with_select, unpack( t, 1, n ) )
  io.write( "{...}  #: ", n, "  " )
  collectgarbage()
  bench( N, with_table, unpack( t, 1, n ) )
  if n < M2 then
    n = n + 1
  else
    n = 2 * n
  end
end