I decided to do some profiling and tinkering and I picked the PerlInt class
since its one of the most common. There is a large gap between our
MOPS benchmarks when using the plain INT registers as opposed to
the PMC regs.

There seems to be much room for optimization in the PMC virtual
methods, even if it means inlining code and breaking OOP reuse
a bit.

For example, profiling mops_p.pbc gives the following...

Each sample counts as 0.01 seconds.
   %   cumulative   self              self     total
  time   seconds   seconds    calls  ms/call  ms/call  name
  52.73      2.32     2.32        1  2320.00  2320.00  cg_core
  17.95      3.11     0.79 
Parrot_PerlInt_subtract_i
nt
  13.41      3.70     0.59                             Parrot_PerlInt_get_bool
   8.86      4.09     0.39 
Parrot_PerlInt_subtract_b
int
   7.05      4.40     0.31 
Parrot_PerlInt_set_intege
r_native
   0.00      4.40     0.00      642     0.00     0.00  add_to_free_pool
   0.00      4.40     0.00       60     0.00     0.00  mem_sys_allocate
   0.00      4.40     0.00       29     0.00     0.00  mem_allocate


So taking a look at PerlInt, I notice that subtract_int calls the
method set_integer_native. Now, the reasons for encapsulation
for methods for "setting" the core value in an object are not lost
on me, however I think the core PMCs are one place where we
should inline as much as possible. All set_integer_native does
is sets the value for now, I can't think of many other things
to actually encapsulate inside it.

There is the case where we might derive from PerlInt and the
child class reimplements its set_native, but I'm not sure that
this OOP constraint should dictate losing 10Million ops/sec, as
it does on my box.

Going from:

     void subtract_int (INTVAL value, PMC* dest) {
             dest->vtable->set_integer_native(INTERP, dest,
                 SELF->cache.int_val - value
         );
     }

To:

     void subtract_int (INTVAL value, PMC* dest) {
           dest->cache.int_val -= value;
     }


Takes mops_p.pbc from:

     Stock:
     Elapsed time:  4.342769
     M op/s:        46.053566

To:

     Modified:
     Elapsed time:  3.619222
     M op/s:        55.260495


Granted, doing this means, if I make a new PMC that uses the PerlInt
vtable, then if I were to override set_int_native(), the rest of my inlined
ops would need overriding as well, however, realistically, I'm not
concerned that the PMC internals be an elegant OOP framework, when
it means losing this much performance.

What if we specifiy certain PMC classes as "final"? All that might mean is
we say, if you derive from a final PMC, you must expect:

1) To reimplement most of the vtable
2) To not rely on that PMC's interface never changing


Yeh I know that word is yucky and from Java land, but in this case, I think 
that
"system" PMCs should take liberties for optimization.

-Melvin

Reply via email to