Skip to content

Commit

Permalink
- Optimizations in the RangeNum class (+cache for small values).
Browse files Browse the repository at this point in the history
This improves considerably the performance of `for` loops and iterations over ranges in general.

Example:

	for (1..1e6) { }  	# this now takes ~1.4s (previously took ~2s)
  • Loading branch information
trizen committed Oct 29, 2019
1 parent 968c96f commit 0527937
Show file tree
Hide file tree
Showing 6 changed files with 80 additions and 35 deletions.
4 changes: 2 additions & 2 deletions lib/Sidef/Object/Lazy.pm
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ package Sidef::Object::Lazy {

my $iter = $self->{obj}->iter;

ITEM: while (defined(my $item = $iter->run())) {
my @arg = ($item);
ITEM: for (; ;) {
my @arg = ($iter->run() // last);
foreach my $call (@{$self->{calls}}) {
@arg = $call->(@arg);
@arg || next ITEM;
Expand Down
8 changes: 8 additions & 0 deletions lib/Sidef/Types/Array/Array.pod
Original file line number Diff line number Diff line change
Expand Up @@ -1624,6 +1624,14 @@ Return the

=cut

=head2 segment_by

Array.segment_by() -> I<Obj>

Return the

=cut

=head2 shift

Array.shift() -> I<Obj>
Expand Down
5 changes: 3 additions & 2 deletions lib/Sidef/Types/Number/Number.pm
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@ package Sidef::Types::Number::Number {
LONG_MIN => Math::GMPq::_long_min(),
};

our ($ROUND, $PREC, $MPZ);
our ($ROUND, $PREC);

BEGIN {
$ROUND = Math::MPFR::MPFR_RNDN();
$PREC = 192;
$MPZ = bless \Math::GMPz::Rmpz_init();
}

my $MPZ = bless \Math::GMPz::Rmpz_init();

state $round_z = Math::MPFR::MPFR_RNDZ();

state $ONE = Math::GMPz::Rmpz_init_set_ui(1);
Expand Down
58 changes: 34 additions & 24 deletions lib/Sidef/Types/Range/Range.pm
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ package Sidef::Types::Range::Range {
$_[0]->{_cached_array} //= do {
my @array;
my $iter = $_[0]->iter;
while (1) {
push @array, $iter->run() // last;
for (; ;) {
push @array, ($iter->run() // last);
}
\@array;
};
Expand Down Expand Up @@ -145,7 +145,8 @@ package Sidef::Types::Range::Range {

my $iter = $self->iter;

while (defined(my $obj = $iter->run())) {
for (; ;) {
my $obj = $iter->run() // last;
return $obj if $block->run($obj);
}

Expand Down Expand Up @@ -244,8 +245,9 @@ package Sidef::Types::Range::Range {
my ($self, $block) = @_;

my $iter = $self->iter;
while (defined(my $obj = $iter->run())) {
$block->run($obj);

for (; ;) {
$block->run($iter->run() // last);
}

$self;
Expand All @@ -261,8 +263,9 @@ package Sidef::Types::Range::Range {

my @values;
my $iter = $self->iter;
while (defined(my $obj = $iter->run())) {
push @values, $block->run($obj);

for (; ;) {
push @values, $block->run($iter->run() // last);
}

Sidef::Types::Array::Array->new(\@values);
Expand All @@ -275,7 +278,9 @@ package Sidef::Types::Range::Range {

my @values;
my $iter = $self->iter;
while (defined(my $obj = $iter->run())) {

for (; ;) {
my $obj = $iter->run() // last;
push(@values, $obj) if $block->run($obj);
}

Expand All @@ -290,8 +295,9 @@ package Sidef::Types::Range::Range {
$block //= Sidef::Types::Block::Block::IDENTITY;

my $iter = $self->iter;
while (defined(my $obj = $iter->run())) {
$block->run($obj)

for (; ;) {
$block->run($iter->run() // last)
&& return Sidef::Types::Bool::Bool::TRUE;
}

Expand All @@ -304,8 +310,9 @@ package Sidef::Types::Range::Range {
$block //= Sidef::Types::Block::Block::IDENTITY;

my $iter = $self->iter;
while (defined(my $obj = $iter->run())) {
$block->run($obj)

for (; ;) {
$block->run($iter->run() // last)
|| return Sidef::Types::Bool::Bool::FALSE;
}

Expand All @@ -318,8 +325,9 @@ package Sidef::Types::Range::Range {
$block //= Sidef::Types::Block::Block::IDENTITY;

my $iter = $self->iter;
while (defined(my $obj = $iter->run())) {
$block->run($obj)

for (; ;) {
$block->run($iter->run() // last)
&& return Sidef::Types::Bool::Bool::FALSE;
}

Expand All @@ -331,8 +339,9 @@ package Sidef::Types::Range::Range {

my @array;
my $iter = $self->iter;
while (defined(my $obj = $iter->run())) {
push @array, $obj;

for (; ;) {
push @array, ($iter->run() // last);
}

Sidef::Types::Array::Array->new(\@array);
Expand All @@ -353,8 +362,9 @@ package Sidef::Types::Range::Range {

my @array;
my $iter = $self->iter;
while (defined(my $obj = $iter->run())) {
push @array, $obj;

for (; ;) {
push @array, ($iter->run() // last);
}

(@array);
Expand Down Expand Up @@ -454,8 +464,8 @@ package Sidef::Types::Range::Range {
my $count = 0;
my $iter = $self->iter;

while (defined(my $obj = $iter->run())) {
++$count if $arg->run($obj);
for (; ;) {
++$count if $arg->run($iter->run() // last);
}

Sidef::Types::Number::Number->_set_uint($count);
Expand Down Expand Up @@ -485,8 +495,8 @@ package Sidef::Types::Range::Range {
my $iter = $self->iter;
my $value = $initial // $iter->run();

while (defined(my $obj = $iter->run())) {
$value = $op->run($value, $obj);
for (; ;) {
$value = $op->run($value, $iter->run() // last);
}

return $value;
Expand All @@ -503,8 +513,8 @@ package Sidef::Types::Range::Range {
my $iter = $self->iter;
my $value = $initial // $iter->run();

while (defined(my $num = $iter->run())) {
$value = $value->$op($num);
for (; ;) {
$value = $value->$op($iter->run() // last);
}

$value;
Expand Down
36 changes: 31 additions & 5 deletions lib/Sidef/Types/Range/RangeNumber.pm
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ package Sidef::Types::Range::RangeNumber {
use Sidef::Types::Bool::Bool;
use Sidef::Types::Number::Number;

my $MPZ = bless(\Math::GMPz::Rmpz_init(), 'Sidef::Types::Number::Number');

require Devel::Peek;

sub new {
my (undef, $from, $to, $step) = @_;

Expand Down Expand Up @@ -43,14 +47,15 @@ package Sidef::Types::Range::RangeNumber {

*call = \&new;

my @cache;

sub iter {
my ($self) = @_;

my $step = $self->{step};
my $from = $self->{from};
my $to = $self->{to};

my $tmp;
my $times = ($self->{_times} //= $to->sub($from)->add($step)->div($step));

if (ref($times) eq 'Sidef::Types::Number::Number') {
Expand Down Expand Up @@ -80,9 +85,23 @@ package Sidef::Types::Range::RangeNumber {
return Sidef::Types::Block::Block->new(
code => sub {
--$repetitions >= 0 or return undef;
$tmp = bless(\Math::GMPz::Rmpz_init_set_si($from), 'Sidef::Types::Number::Number');

if ($from <= 8192 and $from >= 0) {
my $obj = ($cache[$from] //=
bless(\Math::GMPz::Rmpz_init_set_ui($from), 'Sidef::Types::Number::Number'));
$from += $step;
return $obj;
}

if (Devel::Peek::SvREFCNT($$MPZ) > 1) {
$MPZ = bless(\Math::GMPz::Rmpz_init_set_si($from), 'Sidef::Types::Number::Number');
}
else {
Math::GMPz::Rmpz_set_si($$MPZ, $from);
}

$from += $step;
$tmp;
$MPZ;
},
);
}
Expand All @@ -92,16 +111,23 @@ package Sidef::Types::Range::RangeNumber {
return Sidef::Types::Block::Block->new(
code => sub {
--$repetitions >= 0 or return undef;
$tmp = bless(\Math::GMPz::Rmpz_init_set($counter_mpz), 'Sidef::Types::Number::Number');
if (Devel::Peek::SvREFCNT($$MPZ) > 1) {
$MPZ = bless(\Math::GMPz::Rmpz_init_set($counter_mpz), 'Sidef::Types::Number::Number');
}
else {
Math::GMPz::Rmpz_set($$MPZ, $counter_mpz);
}

Math::GMPz::Rmpz_add($counter_mpz, $counter_mpz, $step);
$tmp;
$MPZ;
},
);
}
}

my $asc = ($self->{_asc} //= !!($step->is_pos // return Sidef::Types::Block::Block->new(code => sub { undef; })));

my $tmp;
Sidef::Types::Block::Block->new(
code => sub {
($asc ? $from->le($to) : $from->ge($to)) || return undef;
Expand Down
4 changes: 2 additions & 2 deletions scripts/RosettaCode/read_a_file_line_by_line.sf
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
## http://rosettacode.org/wiki/Read_a_file_line_by_line
#

File.new(__FILE__).open_r.each { |line|
print line;
File(__FILE__).open_r.each { |line|
say line;
}

0 comments on commit 0527937

Please sign in to comment.