lua-users home
lua-l archive

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


On Monday 31 January 2005 06.12, skaller wrote:
[...]
> > At least, EEL calls C and EEL functions the same way, 
> 
> Yes, but Lua does not. More precisely it has to lookup
> the function by name at some point, and the function,
> if defined in C, has to have the Lua C function interface.

EEL only looks up functions by name when calling through typeless 
object references. OTOH, that could mean most of the time, depending 
on your programming style. :-)

BTW, I'm working on an enum type that allows "recasting" values across 
enums. With some optimizations, using that for indexing stuff won't 
cost more than indexing with an integer most of the time, and at most 
a table lookup to recast when you happen to get the right name from 
the wrong enum.


> > To install a bytecode operator, on would just set the bytecode 
> > function pointer to it, and then point the C function pointer to a 
> > function that performs a VM call instead of actually performing an 
> > operation. No performance penalty for native implementations!
> 
> You're missing the point though. Even if a C function were
> called, it is unlikely to be as efficient as the current 
> Lua bytecode interpreter adding Number + Number because that
> case is specially treated:
> 
>       case OP_ADD: {
>         TObject *rb = RKB(i);
>         TObject *rc = RKC(i);

((GETARG_B(i) < MAXSTACK) ? RB(i) : k+GETARG_B(i)-MAXSTACK)
((GETARG_C(i) < MAXSTACK) ? RC(i) : k+GETARG_C(i)-MAXSTACK)

2 conditional branches

(Which the EEL VM doesn't have BTW. The obvious side effect is that it 
needs more opcodes, but those are handled by the main instruction 
decode switch() which cannot be avoided anyway. Bad news is I might 
hit cache limits on some archs if I take that approach too far...)


>         if (ttisnumber(rb) && ttisnumber(rc)) {

(ttype(rb) == LUA_TNUMBER) && (ttype(rc) == LUA_TNUMBER)

2 conditional branches


>           setnvalue(ra, nvalue(rb) + nvalue(rc));
>         }
>         else
>           Arith(L, ra, rb, rc, TM_ADD);
>         break;
>       }
> 
> Arith() is messy, it calls another function which tries
> metamethods. But for a native Number type the code involves
> two types checks and this line:
> 
>           setnvalue(ra, nvalue(rb) + nvalue(rc));
> 
> which is basically a native C level + operation.
> 
> The point being that without some care of the implementation
> details, a more general system might degrade performance
> of 'the usual case' significantly which probably isn't acceptable.

Yeah... Can't have everything. :-)

However, my point is that even with inline special cases like those in 
Lua, and those I used to have in EEL, still involve some conditionals 
- and those waste large numbers of cycles very frequently.

It should also be noted that VM instruction decoding burns a major 
part of the cycles when doing simple operations like this, so +/-50% 
on the actual operation isn't going to impact overall performance all 
that much.

Of course, speed can't hurt, but there *are* other languages that are 
more appropriate than Lua or EEL or any other VM based solution when 
every cycle matters. ;-)


Anyway, they way the EEL operator subsystem is structured now, it 
shouldn't be too hard (some cut'n'paste work, mostly) to convert it 
to use a [type][operator][type] array instead of the current switch() 
+ messy metamethod logic. Would be interesting to see what kind of 
impact that would have on performance.


//David Olofson - Programmer, Composer, Open Source Advocate

.- Audiality -----------------------------------------------.
|  Free/Open Source audio engine for games and multimedia.  |
| MIDI, modular synthesis, real time effects, scripting,... |
`-----------------------------------> http://audiality.org -'
   --- http://olofson.net --- http://www.reologica.se ---