lua-users home
lua-l archive

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


On Fri, 15 Aug 2014 17:31:10 +0200
Jan Behrens <jbe-lua-l@public-software-group.org> wrote:

> On Fri, 15 Aug 2014 16:53:55 +0200
> Jan Behrens <jbe-lua-l@public-software-group.org> wrote:
> 
> > I will do further benchmarks on this.
> 
> 
> I just created a patched Lua 5.3, which differs from Lua 5.3-alpha as
> follows:
> 
> --- lua-5.3.0-alpha/src/lbaselib.c      2014-07-24 21:33:29.000000000 +0200
> +++ lua-5.3.0-alpha-staticlen/src/lbaselib.c    2014-08-15 17:17:32.078783582 +0200
> @@ -260,7 +260,11 @@
>  */
>  static int ipairsaux (lua_State *L) {
>    int i = luaL_checkint(L, 2) + 1;
> -  if (i > luaL_len(L, 1)) {  /* larger than length? */
> +  int maxi;
> +  lua_settop(L, 2);
> +  lua_pushinteger(L, 10000);  
> +  maxi = luaL_checkint(L, 3);
> +  if (i > maxi) {  /* larger than length? */
>      lua_pushnil(L);  /* end traversal */
>      return 1;
>    }
> 
> This is to simulate the length being passed as 3rd argument to
> ipairsaux.
> 
> Now I reused my benchmark:
> 
> ========================================
> dynamic-length.lua:
> 
> datatable = {}
> 
> for i = 1, 10000 do
>   datatable[i] = tostring(i)
> end
> 
> proxytable = setmetatable({}, {
>   __index = datatable,
>   __len = function() return #datatable end,
>   __ipairs = function(t)
>     return ipairs(datatable)
>   end
> })
> 
> local yes = 0
> local no = 0
> 
> for i = 1, 10000 do
>   for j, v in ipairs(proxytable) do
>     if v then yes = yes + 1 else no = no + 1 end
>   end
> end
> ========================================
> 
> 
> Result with the unpatched Lua 5.3-alpha *without* LUA_COMPAT_IPAIRS:
> 
> ~/lua_ipairs_test/lua53 % time bin/lua ../dynamic-length.lua 
> 114.452u 0.007s 1:55.69 98.9%   259+172k 0+0io 0pf+0w
> 
> 
> Result with the unpatched Lua 5.3-alpha *with* LUA_COMPAT_IPAIRS:
> 
> ~/lua_ipairs_test/lua53compat % time bin/lua ../dynamic-length.lua
> 38.697u 0.000s 0:39.38 98.2%    259+172k 0+0io 0pf+0w
> 
> 
> Result with the *patched* Lua 5.3-alpha *without* LUA_COMPAT_IPAIRS:
> 
> ~/lua_ipairs_test/lua53patched % time bin/lua ../dynamic-length.lua
> 51.611u 0.007s 0:52.27 98.7%    259+172k 0+0io 3pf+0w
> 
> 
> I would thus conclude that my previously brought up argument in 3. a)
> is valid, but only results in a slowdown of a factor of 1.33
> (51.611 seconds versus 38.697 seconds).

I need to add something here: The factor of 1.33 only applies to my
scenario outlined in the benchmark above, having made the following
assumptions:

* __index points directly to a table (it's not a function)
* __len is a Lua function that applies the # operator to a
  global variable

If I modify the benchmark in such way that

* __index is a more expensive Lua function
* __len is a less expensive Lua function (applying the # operator to a
  local instead of global variable)

then I get different results.

Here is a new benchmark with these modified assumptions:

========================================
index-func.lua:

local datatable = {}  -- local keyword improves performance

for i = 1, 10000 do
  datatable[i] = tostring(i)
end

proxytable = setmetatable({}, {
  __index = function(t, k) rawget(t, k) end,
  __len = function() return #datatable end,
  __ipairs = function(t)
    return ipairs(datatable)
  end
})

local yes = 0
local no = 0

for i = 1, 10000 do
  for j, v in ipairs(proxytable) do
    if v then yes = yes + 1 else no = no + 1 end
  end
end
========================================

With the following results:

~/lua_ipairs_test/lua53 % time bin/lua ../index-func.lua
159.914u 0.000s 2:42.45 98.4%   259+172k 0+0io 0pf+0w

~/lua_ipairs_test/lua53compat % time bin/lua ../index-func.lua
38.443u 0.000s 0:39.01 98.5%    258+172k 0+0io 0pf+0w

~/lua_ipairs_test/lua53patched % time bin/lua ../index-func.lua
96.750u 0.000s 1:37.79 98.9%    259+172k 0+0io 0pf+0w


Removing __ipairs and caching the length (simulated with my patch
above) yields to a slowdown of a factor of 2.52 (96.750 seconds versus
38.443 seconds) in this new example scenario.

Removing __ipairs and not caching the length yields to a slowdown of a
factor of 4.16 (159.914 seconds versus 38.443 seconds) in this new
example scenario.


Regards
Jan