lua-users home
lua-l archive

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


Hi David,

> How critical is that requirement really?  For a serializer I would
> probably first serialize the integer elements 1..#t using a numeric for
> loop and then use pairs and filter out all integer keys <= #t.  Of
> course you would iterate over the integer keys twice, but I wonder
> whether the cost for filtering out the elements would be significant
> compared to the entire cost for serialization.

This is not critical and in fact it is exactly what I do, but it is
noticeably slower than just getting the integer elements. Here are the
results from a simple benchmark I have for a table with 100000 numeric
only keys (Windows 32bit, lua 5.2.1):

maxn (100): 0.967s --<-- just 1..#t
maxnpairs (100): 3.448s --<-- 1..#t plus pairs with checks; nothing new added
pairsnum (100): 2.605s --<-- pairs with o[n] = key
pairs (100): 4.368s --<-- pairs with o[#o+1] = key
pairsins (100): 5.991s --<-- pairs with table.insert(o, key)

So, maxn+pairs is 3x slower than just 1..#t for this particular case.
Obviously it's only part of the serialization processing, so it's not
going to be 3x faster, but it can be avoided for a cost of a check (if
it's available). Here is the script:

local insert = table.insert
local ITERS = 100
local TESTS = {
  maxn = function(t)
    local o, maxn, n = {}, #t, 0
    for key = 1, maxn do o[key] = key end
  end,
  maxnpairs = function(t)
    local o, maxn, n = {}, #t, 0
    for key = 1, maxn do o[key] = key end
    for key in pairs(t) do if o[key] ~= key then n = n + 1; o[n] = key end end
  end,
  pairs = function(t)
    local o = {}
    for key in pairs(t) do o[#o+1] = key end
  end,
  pairsnum = function(t)
    local o, n = {}, 0
    for key in pairs(t) do n = n + 1; o[n] = key end
  end,
  pairsins = function(t)
    local o, n = {}, 0
    for key in pairs(t) do insert(o, key) end
  end,
}

local a = {}
for i = 1, 100000 do a[i] = i end

for test, func in pairs(TESTS) do
  local start = os.clock()
  for _ = 1, ITERS do func(a) end
  print(("%s (%d): %ss"):format(test, ITERS, os.clock() - start))
end

Paul.