You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@lucy.apache.org by Marvin Humphrey <ma...@rectangular.com> on 2007/11/07 21:50:24 UTC

Indirect dispatch a success

[cross posted to the KinoSearch and Lucy dev lists]

Greets,

Indirect dispatch is now a part of KinoSearch as of revision r2610.

Method calls look like they did before:

     HitQ_Insert(hit_q, score_doc);

But the macros have changed:

   /* Before */
   #define Kino_HitQ_Insert(self, element) \
     (self)->_->insert((kino_PriorityQueue*)self, element)

   /* After */
   #define Kino_HitQ_Insert(self, element) \
     (((kino_PriQ_insert_t)((self)->_->methods 
[Kino_HitQ_Insert_OFFSET])) \
      ((kino_PriorityQueue*)self, element))

This is how the generated assembler for that macro looks, approximately.

     movl    (%eax), %edx                            # Load HitQueue  
object
                                                     #   into %edx.
     movl    Kino_HitQ_Insert_OFFSET@GOT(%ebx), %eax # Load Global  
Offset Table
                                                     #   pointer  
entry for
                                                     #    
method_OFFSET into %eax.
     movl    (%eax), %eax                            # Dereference  
method_OFFSET,
                                                     #   loading its  
value into
                                                     #   %eax.
     movl    20(%edx,%eax,4), %eax                   # Add the  
address of
                                                     #   self->_- 
 >methods to %eax,
                                                     #   which will  
then hold the
                                                     #   address of a  
pointer to
                                                     #    
kino_HitQ_insert.

A few more instructions must be executed compared with before.   
However, I can detect no impact on performance using the indexing  
benchmark script, even after changing InStream and OutStream from  
FINAL_CLASS to CLASS so that their methods go through the dispatch  
table rather than resolve to function addresses.  I speculate that  
because all the extra instructions are pipeline-able, they're nearly  
indistinguishable from free.

It turns out to be possible to avoid bootstrapping under GCC, but I  
haven't yet come up with a portable hack.   The problem is that while  
you can fake flexible arrays on just about any compiler using  
last_element[1] instead of last_element[], static initialization is a  
bugaboo.  For now I've gone with the static approach, but it warns  
under -pedantic and will probably need to be changed.

To recap, the rationale for this mod is that it removes vtables as a  
source of potential binary incompatibility should a C API be published.

Marvin Humphrey
Rectangular Research
http://www.rectangular.com/