Dan,

As it stands, KEY * is a win when:

  1) All of the array indices are constants and hardcoded into the instruction
     stream
  2) The PMC handling the index does not have to recurse.

In all other cases, as it currently stands, it is a loose. I hate to come out
and be so blunt, but I think this is the culmination of what I've found, and a
lot of people are saying. This approach is penny wise, pound foolish.


  1) KEY *'s and their atoms are allocated from memory. The memory allocation
     hurts more than it saves, cycle wise.
     The number of CPU cycles used doing a virtual machine instruction *pales*
     in comparison to what is needed to allocate memory.
  2) Constants are very seldom used as array indexes, in real code, and almost
     never used exclusively in multidim access. If you had an x*y*z sized array,
     it would take x*y*z statements to access all of its members! Thats hardly
     an expressive language =)
  3) When several PMCs recurse to handle a KEY * request, the system stack
     has everything pop'd off and back on once for each member of the KEY *
     list! If nothing else, refactor this into an iterative thing rather than
     recurisve thing! Create a register that holds KEY * and for gods sake,
     get everything off the system stack.

Given your objectives of speed, generality and elegance, I could propose
several other solutions:

1. PMCs spit out an "inner class" of themselves on demand, that are attached
   to the scalars and arrays that index their parents. When this child PMC
   is accessed, the value indexed by the indices we reference is accessed
   instead. As a container, it is immutable. Reference to the indicing
   PMCs is dropped when we go out of scope or are destroyed.
   Given: $a = $b->[$x]->[$y]->[$z], a $b_delta would be created that
   could be accessed directly: $a = $b_delta. $b_delta would be attached
   to $x, $y, $z. This optimizes cases where the same variables index
   a multidim, even as their values change. This is a real-world case
   that would have real benefits. Put another, it would be like converting:
   $ob->accessor($x, $y, $z) into $new_accessor = sub { ob_accessor($x, $y, $z) }
   allowing you to say $new_accessor->(), omiting $x $y $z,
   but would be a performance gain instead of loss =)
2. PMCs return iterators allocated on a stack that allow them to function as
   KEY *s allocating a single fixed size peice of memory rather than all
   of the parts of a linked list. In other words, factor out the part of
   PMCs that index a given element. This would completely bypass the construction 
   of KEY* lists, and allow PMCs to function as keys. This case needs
   to be optimised, as most keys will be scalars or a few scalars,
   and quickly moving from a scalar to a key should be paramount.
3. Let PMCs create KEY * lists. Whats more, rather than scraping KEY *
   lists of an adequate size and replacing them every iteration in user code
   loops, *update* the KEY* list from PMCs. Eg, if $x is the first item,
   $y is the second, and $z is the third, update the values in the KEY*
   with the new values from the scalars, then shuffle the same KEY * off
   again. Use a load/store strategy! The complexity involved in exposing
   every single method in a contained object damages cache use beyond
   *any* possible benefit! See earlier post for details.

General Philosophical Diatribe:
  
  * count cycles
  * count resources
  * complexity in name of speed should be very carefully scutinized
  * follow malloc() through a debugger sometime - you'll never want to use it again
    case in point, p6 overallocates whereever it can to avoid it in the future
  * function calls consume resources
  * assuming a 2 meg cache on a 2 meg cache makes for a program that works
    *great* on your machine, then proceds to suck pond scum on mine =)
    assuming a 1 meg cache, the program will run marginally slower on yours,
    but an order of magnitude faster on mine
  * caches, virtual memory, and all of their ilk work best when you pretend
    they dont exist. think of them as little faerie helpers - dont demand work,
    and when your shoes are fixed in the morning, leave them a treat ;)
  

Case in point:

Perl 5 runs *awesome* on a 486/25. Java (Kaffe) is completely unusable. 
AWT windows come up in a matter of *days*, whereas a Tk window comes up 
in about 45 seconds. On a fast computer, these things are blurred. The point 
is, you can thrash your system on a faster computer, but register renaming, a 
large L2 cache, lots of disc bandwidth to thrash with etc obscured the fact 
that you are wasting resources horribly.

In summary, I beg Dan to reconsider =)

-scott


On Sun, 21 Jul 2002, Dan Sugalski wrote:

> At 6:58 PM +0200 7/21/02, Josef Höök wrote:
> >
> >That looks something similar what i've been thinking of. If we go further
> >in this thinking why not make KEY , INTVAL , NUM and PMC all pmc's
> >and just call set and get on pmc's.
> 
> Speed. The reason for them is speed. Generality and elegance are 
> nice, but the point is to go faster, which is why the special cases 
> are there.
> -- 
>                                          Dan
> 
> --------------------------------------"it's like this"-------------------
> Dan Sugalski                          even samurai
> [EMAIL PROTECTED]                         have teddy bears and even
>                                        teddy bears get drunk
> 
> 

Reply via email to