[Date Prev][Date Next][Thread Prev][Thread Next]
- Subject: Re: Tables vs closures for representing objects (and JITability)
- From: Matthew Wild <mwild1@...>
- Date: Thu, 12 Nov 2009 16:28:20 +0000
2009/11/12 Mike Pall <email@example.com>:
> Matthew Wild wrote:
>> I've come into a little debate recently. We're working on an API,
>> which will be used to create *lots* of small objects. Performance is
>> critical above everything else (don't shout at me for this :) ).
> Measure first, then optimize.
>> The debate is whether to represent objects the standard way - as
>> tables of methods (the methods being closures for efficiency),
> That's what the __index table is for: shared method lookup across
> instances. Making them closures (over the instance?) is pointless.
>> or as just a single closure each, that takes the method name as
>> its first parameter, and has if/elseif. We're looking at about a
>> dozen fixed methods max per object.
> Why do you want to replace a hash table lookup with a chain of
> linear comparisons? Why do you think you can beat Lua's hash table
> lookup? Hint: you can't.
Fair enough :)
>> The latter seems like it would win out, and produce less garbage, etc.
> No it doesn't. Shared methods have zero per-instance cost. Adding
> a dozen closures for every instance is expensive.
The reason closures are used in the table methods are to avoid useless
self.* table lookups, these *do* make a difference in benchmarks
(though I'm expecting not so much in a JIT).
The closure representation for objects would be a single function, and
the methods would be contained in that. String comparisons in Lua are
fast, and it if/elseif can be faster than table lookups. If LuaJIT
gives us table lookups just as fast then that's good.
>> The downsides are obvious - it isn't possible (well, easily) to add
>> properties to the object dynamically- so I don't want to do it
>> needlessly. Is this the only thing I'm trading for speed?
> Needless complexity comes to mind ...
I'm glancing over that for now - I'd still consider it less complex
than having to write it all in C using the Lua API :)
>> One of the main things I'm also interested in is which approach would
>> be most JIT-friendly. The latter representation of objects is
>> uncommon, so I'm concerned LuaJIT may already be optimised for
>> tables-as-objects, and I'll be wasting my time.
> LJ2 very happily deals with metatables and can hoist most method
> lookups out of the inner loops. And the remaining hash table
> lookups with constant keys are extremely cheap (zero or one
> machine code instruction in the dependency chain). I doubt you can
> make that go any faster ...
That sounds great, but I had not dared hope just in case :)
>> In anticipation of replies... the argument that any gain wouldn't be
>> noticeable and therefore isn't worth it doesn't really hold out...
>> *everything* becomes noticeable once you multiply by a large number :)
> Ah, but, of course. The downsides of this strange approach will
> certainly be noticeable (especially once you're stuck with it).
Quite possibly. But being able to gauge the gains for sacrificing the
"normal" way of doing things before making the decision (not) to is
important I think.