Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Make a faster List.pick(*,:eager) version
Well, that was the idea.  Turns out the eager version is about 20x *slower*.
Added here for further research.

What has been ruled out:
- anything inside the loop
  That part of the code is mostly the same as the non-eager version.  If
  the code inside the while loop is reduced to just the $elems = $elems - 1,
  even then the eager variant is about 15x slower.
- something in the MMD dispatch
  If the code inside the "eager" variant is the same as the non-eager variant,
  there is no difference in execution noticeable either.
- not SPESH related
  With MVM_SPESH_DISABLE=1 the difference in execution is even larger: the
  optimizer did its best!

What *is* different?
- the number of frames in a profile
  example code: my @A = ^100; for ^500 { @a.pick(*) } # or *, :eager
  non-eager / eager: 10618 / 176614 frames
  So the difference in number of frames is in same order of magnitude as the
  difference in CPU.

So the question is really: why does the eager version create so many frames?
  • Loading branch information
lizmat committed Apr 24, 2015
1 parent 14f6344 commit 40a4241
Showing 1 changed file with 21 additions and 0 deletions.
21 changes: 21 additions & 0 deletions src/core/List.pm
Expand Up @@ -181,6 +181,27 @@ my class List does Positional { # declared in BOOTSTRAP
my $elems = self.elems;
$elems ?? self.AT-POS($elems.rand.floor) !! Nil;
}
multi method pick(Whatever, :$eager!) {
return self.pick(*) if !$eager;

fail X::Cannot::Infinite.new(:action<.pick from>) if self.infinite;

my Int $elems = self.elems;
return unless $elems;

my Mu $picked := nqp::clone($!items);
my Int $i;
my Mu $val;
while $elems {
$i = nqp::rand_I(nqp::decont($elems), Int);
$elems = $elems - 1;
# switch them
$val := nqp::atpos($picked,nqp::unbox_i($i));
nqp::bindpos($picked,nqp::unbox_i($i),nqp::atpos($picked,nqp::unbox_i($elems)));
nqp::bindpos($picked,nqp::unbox_i($elems),$val);
}
nqp::p6parcel($picked,Any);
}
multi method pick(Whatever) {
fail X::Cannot::Infinite.new(:action<.pick from>) if self.infinite;

Expand Down

0 comments on commit 40a4241

Please sign in to comment.