lua 3.0a

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

lua 3.0a

Mark Ian Barlow
Could we please have a brief selective text description on the new features
in Lua3.0a? They are given as:

  + NEW CONCEPT: internal methods based on tags replace fallbacks
    (but fully compatible with 2.5)
      *** I've tested the backwards compatibility (no problem) but I'd
      *** be interested to try out the new concept, given a few hints...
  + new, general syntax for constructors {[exp] = exp, ... }
      *** Self-explanatory (or are there implications?).
  + userdata can now handle arbitrary binary data
      *** Not of immediate interest to me, but maybe others...
  + support for handling variable number of arguments in functions (varargs)
      *** This was already explained in this list, as it was present
      *** but undocumented in Lua2.5.
  + support for conditional compilation ($if ... $else ... $end)
      *** Self-explanatory.
  + better support for writing libraries (auxlib.h)
      *** This can be readily understood by reading the source.
  + luac can now also undump
      *** Self-explanatory.

I realise this is a distraction from work on the beta, but it would enable
us to get some code ready to test it with when it is done! I think the
replacement of fallbacks is probably the most important (to me, at least).

--  Mark Ian Barlow                Non-Linear Control Consultants Ltd.
    -----------------------------------------------------------------
    [hidden email]            Voice / Fax: +44 (0)1207 562 154

Reply | Threaded
Open this post in threaded view
|

Re: lua 3.0a

LD Landis
Hi,

  Was there a follow-up to the report of a 4x (runs 4 times longer)
  performance decrease?  If so, I guess I missed it. (Don't have the item
  close at hand, but the performance was measured across a html/latex
  processor I think).

  Just curious if/what/why and if it can be fixed before 3.0.

--
Cheers,
	--ldl
-----------------------------------------------------------------------------
LD Landis [hidden email] N0YRQ    Voice 612/883-5511 Fax 612/883-6363
HealthPartners, 8100 34th Avenue So, PO Box 1309, Minneapolis, MN  55440-1309
Shape your life not from your memories, but from your hopes.       (Borrowed)
Still programming for the day-job... haven't yet gotten that Microsoft PR job
-----------------------------------------------------------------------------

Reply | Threaded
Open this post in threaded view
|

Re: lua 3.0a

Roberto Ierusalimschy
>  Was there a follow-up to the report of a 4x (runs 4 times longer)
>  performance decrease?  If so, I guess I missed it. (Don't have the item
>  close at hand, but the performance was measured across a html/latex
>  processor I think).
>
>  Just curious if/what/why and if it can be fixed before 3.0.

Yes, see below a copy. After that fix, version 3 alpha appears to be
~10-20% slower than version 2.5. We are working on it, and probably the
final version 3.0 will have the same performance or better than 2.5.

-- Roberto


---------- COPY OF PREVIOUS MESSAGE -----------------
To: [hidden email]
Subject: performance of lua 3.0a
In-reply-to: Your message of "Wed, 16 Apr 1997 02:50:43 -0300."
             <19970416084940.58823@...> 
Reply-To: [hidden email]
Date: Wed, 16 Apr 1997 09:42:40 -0300
From: Roberto Ierusalimschy <[hidden email]>

>   An initial test indicates that v3.0a might work OK except for
>   a slowdown by a factor of almost 4 :

  We have detected a "performance bug" in v3.0a which might be responsible
for that. Waldemar Celes has got the same problem, and the profile of his
program starts with:

 18.93%   luaI_travfallbacks
 15.55%   checkfunc
  7.68%   lua_execute

  The problem seems to be in function luaL_arg_check (file auxlib.c). It is
always calling lua_getobjname: This last function is part of the debuger
interface, and it is very very slow (and calls luaI_travfallbacks, which
in turn calls checkfunc). The "bug" is that luaL_arg_check needs to call
lua_getobjname *only* if there is an error, which is very rare. Therefore,
it should be coded like:

void luaL_arg_check(int cond, int numarg, char *extramsg)
{
  if (!cond) {
    char *funcname;
    lua_getobjname(lua_stackedfunction(0), &funcname);
    if (funcname == NULL)
      funcname = "???";
    if (extramsg == NULL)
      luaL_verror("bad argument #%d to function `%s'", numarg, funcname);
    else
      luaL_verror("bad argument #%d to function `%s' (%s)",
                      numarg, funcname, extramsg);
  }
}

(that is, with the call to lua_getobjname inside the "if"). Please try that.


-- Roberto

Reply | Threaded
Open this post in threaded view
|

Re: lua 3.0a

Roberto Ierusalimschy
In reply to this post by Mark Ian Barlow
  I will try a quick explanation. I hope that will be enough for a start.


  + new, general syntax for constructors {[exp] = exp, ... }
      *** Self-explanatory (or are there implications?).

No implications. Just now you can write constructors like:

 a = {f(x), g(y); [h(z)] = u(w)-9, [0] = "hello", ["a b"] = 89}

with the obvious(?) semantics. The old case a = {k = x} is handled as
a syntatic sugar for a = {["k"] = x}, as it was already in normal use
(a.k for a["k"]).


  + userdata can now handle arbitrary binary data
      *** Not of immediate interest to me, but maybe others...

This is still under some internal discussion, but the idea is that you
can store any data (with any size) in a userdata. The operations for that
are:

void           lua_pushbindata          (void *buff, int size, int tag);

-- Gives to Lua a userdata (Lua makes a copy of it, like it does with
strings).

void          *lua_getbindata           (lua_Object object);
int            lua_getbindatasize       (lua_Object object);

-- Get contents and size of a userdata. Again like strings, Lua gives
a pointer to its internal copy, so the program *cannot* change this
data. Notice that userdatas are values, not memory. You cannot use
them like arrays, for instance (i.e. they are immutable). But they
can store any binary information you want.


  + support for conditional compilation ($if ... $else ... $end)
      *** Self-explanatory.

Some details: in "$if x", x can be "1", "nil" or the name of a global
variable. $ifs can be nested. You also have "$ifnot". There is an
extra pragma, $endinput, with the obvious(?) meaning.


  + NEW CONCEPT: internal methods based on tags replace fallbacks
    (but fully compatible with 2.5)
      *** I've tested the backwards compatibility (no problem) but I'd
      *** be interested to try out the new concept, given a few hints...

This is the hardest part. The general idea: internal methods (or tag
methods, or just fallbacks :-) is mainly the old concept of fallbacks,
with one big, and some small differences:

+ instead of being globally defined, each tag can have its own set of methods. 
- like userdata, tables can have different tags.
- to use tag methods, tags must be explicitly created with "newtag".
- tables now also have tag methods for gettable and settable.

  Well, see example below :-)

tt = newtag()
t1 = {5,6,"noite"}
settag(t1, tt)    -- table t1 now has tag tt

function f(t, i)
   return rawgettable(t, i)+3   -- rawgettable is a way to index a table
                                -- without calling tag methods.
end

settagmethod(tt, 'gettable', f)   -- change the method associated with
                                  -- tag 'tt'

assert(t1[1] == 8)  -- since t1 has tag tt, t1[1] will call the
-- internal method for the event 'gettable' associated with 'tt',
-- like an old fallback. Other tables (with other tags) work without changes.


Other details:

- fallback 'arith' has been splited in many tag methods: 'add', 'sub',
'mul', etc. The same for 'order'.

- since userdata are immutable, you cannot use "settag" for them. Instead,
they must be created with their final tag.

- old tags (user defined, without using newtag) can still be used, but
you cannot associate a tag method to them.

- the old function "setfallback" uses the new tag methods in some
complex ways to fully simullate its old behavior.

- the tag methods for getglobal and setglobal (new) are more powerful.
"a = b" calls the tag method of event "setglobal" of "a", it its has one.
An access to a global variable 'b' calls the tag method of event
"getglobal" of "b", it its has one. Notice that setglobal gets its
tag from the original value of the variable, not the new one. This may
sounds strange, but it is very powerful. After you set a proper value
in a global variable, you can have complete control over all accesses
and assignments to it (see example(?) below).

  For more information, look at the file below. It is a test file for
this mechanism. It is far from self-explanatory, but it is not completely
criptographic. But please notice that some things may still change till
final version 3.0.

-- Roberto


$debug
print('testando tags e internal methods')

assert(tag(2) == tag(0) and tag{} == tag{})

tt = newtag()
tt2 = newtag()

t1 = {5,6,"noite"}
settag(t1, tt)
assert(type(t1) == 'table' and tag(t1) == tt)

t2 = {1,2,"alo"}
settag(t2, tt2)

t3 = {10,2,3}

function f(t, i) return rawgettable(t, i)+3 end
assert(gettagmethod(tt, 'gettable') == nil)
assert(settagmethod(tt, 'gettable', f) == nil)
assert(gettagmethod(tt, 'gettable') == f)
assert(settagmethod(tt, 'gettable', f) == f)

function f(t, i, v) rawsettable(t, i, v-3) end
settagmethod(tt, 'settable', f)


assert(t1[1] == 8)
assert(rawgettable(t1, 1) == 5)
assert(t2[3] == 'alo')
assert(rawgettable(t1, 3) == "noite")
assert(rawgettable(t2, 1) == 1)

t1.x = 10
assert(rawgettable(t1, 'x') == 7)
assert(t1.x == 10)
settagmethod(tt, 'gettable', nil)
assert(t1.x == 7)

t2.x = 10
assert(rawgettable(t2, 'x') == t3[1])
assert(t2.x == 10)
print('+')

function f(t, p1) return rawgettable(t, p1) end
settagmethod(tt, 'function', f)

assert(t1(3) == 'noite')

t2.x = 'alo'
function f (s1, s2)
  if type(s1) == 'table' then s1 = s1.x end
  if type(s2) == 'table' then s2 = s2.x end
  return s1..s2
end
settagmethod(tt2, 'concat', f)
assert(t2..'x' == 'alox')
assert('a'..t2 == 'aalo')

tt = newtag()
x = {realvalue = 0}
settag(x, tt)
assert(tag(x) == tt)

function fs (name, oldvalue, newvalue)
  oldvalue.realvalue = newvalue   -- modifica o realvalue
  y = newvalue
end
settagmethod(tt, 'setglobal', fs)

function fg (name, value)
  return value.realvalue   -- retorna valor 'real' de x
end
settagmethod(tt, 'getglobal', fg)

x = 10
assert(x == 10 and y == 10 and getglobal('x') == 10 and
       type(rawgetglobal('x')) == 'table')

setglobal('x', print)
assert(x == print and y == print and getglobal('x') == print and
       type(rawgetglobal('x')) == 'table')

rawsetglobal('x', 4)
x = 12
assert(x == 12 and y == print)

print('+')

tt = newtag()
x = userdata({0, 1, 2}, tt)
assert(type(x) == 'userdata' and tag(x) == tt and
getbyte(x) == 3 and getbyte(x, 3) == 2)

function fs (name, oldvalue, newvalue)
  local u = userdata({newvalue}, tag(oldvalue))
  rawsetglobal(name, u)
end
settagmethod(tt, 'setglobal', fs)

function fg (name, value)
  return getbyte(value, 1)
end
settagmethod(tt, 'getglobal', fg)

x = 10
assert(x == 10 and getglobal('x') == 10)
assert(type(rawgetglobal('x')) == 'userdata' and
       tag(rawgetglobal('x')) == tt)

x = 13
assert(x == 13 and getglobal('x') == 13)
assert(type(rawgetglobal('x')) == 'userdata' and
       tag(rawgetglobal('x')) == tt)

rawsetglobal('x', nil); fs = nil; fg = nil;
assert(x == nil)

print('OK')

return 12