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
>
>