Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Give Hash.pairs/kv/keys/values/antipairs pull-all
my @ = %h.pairs       30% faster
my @ = %h.keys        30% faster
my @ = %h.values      30% faster
my @ = %h.kv          2x as fast
my @ = %h.antipairs   3x as fast

Also now uses a role to factor out the common stuff.  This role also
contains a count-only method, which is the same for all of these methods.
  • Loading branch information
lizmat committed Oct 2, 2015
1 parent ef814c3 commit 2fb63c7
Showing 1 changed file with 66 additions and 44 deletions.
110 changes: 66 additions & 44 deletions src/core/Map.pm
Expand Up @@ -59,18 +59,25 @@ my class Map does Iterable does Associative { # declared in BOOTSTRAP
method iterator(Map:) { self.pairs.iterator }
method list(Map:) { self.pairs.cache }

multi method pairs(Map:D:) {
$!storage := nqp::hash() unless $!storage.DEFINITE;
Seq.new(class :: does Iterator {
has $!hash-iter;

method new(\hash) {
my \iter = self.CREATE;
nqp::bindattr(iter, self, '$!hash-iter',
nqp::iterator(nqp::getattr(hash, Map, '$!storage')));
iter
}
my role MapIterator does Iterator { # needs to be my for some reason
has $!hash-storage;
has $!hash-iter;

method BUILD(\hash) {
$!hash-storage := nqp::getattr(hash, Map, '$!storage');
$!hash-storage := nqp::hash() unless $!hash-storage.DEFINITE;
$!hash-iter := nqp::iterator($!hash-storage);
self
}
method new(\hash) { nqp::create(self).BUILD(hash) }
method count-only() {
$!hash-iter := Mu;
nqp::p6box_i(nqp::elems($!hash-storage))
}
}

multi method pairs(Map:D:) {
Seq.new(class :: does MapIterator {
method pull-one() {
if $!hash-iter {
my \tmp = nqp::shift($!hash-iter);
Expand All @@ -80,40 +87,34 @@ my class Map does Iterable does Associative { # declared in BOOTSTRAP
IterationEnd
}
}
method push-all($target) {
while $!hash-iter {
my \tmp = nqp::shift($!hash-iter);
$target.push(
Pair.new(nqp::iterkey_s(tmp), nqp::iterval(tmp)));
}
IterationEnd
}
}.new(self))
}
multi method keys(Map:D:) {
$!storage := nqp::hash() unless $!storage.DEFINITE;
Seq.new(class :: does Iterator {
has $!hash-iter;

method new(\hash) {
my \iter = self.CREATE;
nqp::bindattr(iter, self, '$!hash-iter',
nqp::iterator(nqp::getattr(hash, Map, '$!storage')));
iter
}

Seq.new(class :: does MapIterator {
method pull-one() {
$!hash-iter
?? nqp::iterkey_s(nqp::shift($!hash-iter))
!! IterationEnd
}
method push-all($target) {
$target.push(nqp::iterkey_s(nqp::shift($!hash-iter)))
while $!hash-iter;
IterationEnd
}
}.new(self))
}
multi method kv(Map:D:) {
$!storage := nqp::hash() unless $!storage.DEFINITE;
Seq.new(class :: does Iterator {
has $!hash-iter;
Seq.new(class :: does MapIterator {
has int $!on-value;

method new(\hash) {
my \iter = self.CREATE;
nqp::bindattr(iter, self, '$!hash-iter',
nqp::iterator(nqp::getattr(hash, Map, '$!storage')));
iter
}

method pull-one() is raw {
if $!on-value {
$!on-value = 0;
Expand All @@ -128,29 +129,50 @@ my class Map does Iterable does Associative { # declared in BOOTSTRAP
IterationEnd
}
}
method push-all($target) {
while $!hash-iter {
my \tmp = nqp::shift($!hash-iter);
$target.push(nqp::iterkey_s(tmp));
$target.push(nqp::iterval(tmp));
}
IterationEnd
}
}.new(self))
}
multi method values(Map:D:) {
$!storage := nqp::hash() unless $!storage.DEFINITE;
Seq.new(class :: does Iterator {
has $!hash-iter;

method new(\hash) {
my \iter = self.CREATE;
nqp::bindattr(iter, self, '$!hash-iter',
nqp::iterator(nqp::getattr(hash, Map, '$!storage')));
iter
}

Seq.new(class :: does MapIterator {
method pull-one() is raw {
$!hash-iter
?? nqp::iterval(nqp::shift($!hash-iter))
!! IterationEnd
}
method push-all($target) {
$target.push(nqp::iterval(nqp::shift($!hash-iter)))
while $!hash-iter;
IterationEnd
}
}.new(self))
}
multi method antipairs(Map:D:) {
self.map: { .value => .key }
Seq.new(class :: does MapIterator {
method pull-one() {
if $!hash-iter {
my \tmp = nqp::shift($!hash-iter);
Pair.new( nqp::iterval(tmp), nqp::iterkey_s(tmp) )
}
else {
IterationEnd
}
}
method push-all($target) {
while $!hash-iter {
my \tmp = nqp::shift($!hash-iter);
$target.push(
Pair.new( nqp::iterval(tmp), nqp::iterkey_s(tmp) ));
}
IterationEnd
}
}.new(self))
}
multi method invert(Map:D:) {
self.map: { (.value »=>» .key).cache.Slip }
Expand Down

0 comments on commit 2fb63c7

Please sign in to comment.