зеркало из https://github.com/github/ruby.git
move Integer#downto to Ruby
Speeds up ChunkyPNG. The interpreter is about 70% faster: ``` before: ruby 3.4.0dev (2024-07-03T15:16:17Z master786cf9db48
) [arm64-darwin23] after: ruby 3.4.0dev (2024-07-03T15:32:25Z ruby-downto 0b8b744ce2) [arm64-darwin23] ---------- ----------- ---------- ---------- ---------- ------------- ------------ bench before (ms) stddev (%) after (ms) stddev (%) after 1st itr before/after chunky-png 892.2 0.1 526.3 1.0 1.65 1.70 ---------- ----------- ---------- ---------- ---------- ------------- ------------ Legend: - after 1st itr: ratio of before/after time for the first benchmarking iteration. - before/after: ratio of before/after time. Higher is better for after. Above 1 represents a speedup. ``` YJIT is 2.5x faster: ``` before: ruby 3.4.0dev (2024-07-03T15:16:17Z master786cf9db48
) +YJIT [arm64-darwin23] after: ruby 3.4.0dev (2024-07-03T15:32:25Z ruby-downto 0b8b744ce2) +YJIT [arm64-darwin23] ---------- ----------- ---------- ---------- ---------- ------------- ------------ bench before (ms) stddev (%) after (ms) stddev (%) after 1st itr before/after chunky-png 709.4 0.1 278.8 0.3 2.35 2.54 ---------- ----------- ---------- ---------- ---------- ------------- ------------ Legend: - after 1st itr: ratio of before/after time for the first benchmarking iteration. - before/after: ratio of before/after time. Higher is better for after. Above 1 represents a speedup. ```
This commit is contained in:
Родитель
cbc40aca3a
Коммит
f4b313f733
45
numeric.c
45
numeric.c
|
@ -5623,50 +5623,6 @@ int_downto_size(VALUE from, VALUE args, VALUE eobj)
|
||||||
return ruby_num_interval_step_size(from, RARRAY_AREF(args, 0), INT2FIX(-1), FALSE);
|
return ruby_num_interval_step_size(from, RARRAY_AREF(args, 0), INT2FIX(-1), FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* call-seq:
|
|
||||||
* downto(limit) {|i| ... } -> self
|
|
||||||
* downto(limit) -> enumerator
|
|
||||||
*
|
|
||||||
* Calls the given block with each integer value from +self+ down to +limit+;
|
|
||||||
* returns +self+:
|
|
||||||
*
|
|
||||||
* a = []
|
|
||||||
* 10.downto(5) {|i| a << i } # => 10
|
|
||||||
* a # => [10, 9, 8, 7, 6, 5]
|
|
||||||
* a = []
|
|
||||||
* 0.downto(-5) {|i| a << i } # => 0
|
|
||||||
* a # => [0, -1, -2, -3, -4, -5]
|
|
||||||
* 4.downto(5) {|i| fail 'Cannot happen' } # => 4
|
|
||||||
*
|
|
||||||
* With no block given, returns an Enumerator.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
static VALUE
|
|
||||||
int_downto(VALUE from, VALUE to)
|
|
||||||
{
|
|
||||||
RETURN_SIZED_ENUMERATOR(from, 1, &to, int_downto_size);
|
|
||||||
if (FIXNUM_P(from) && FIXNUM_P(to)) {
|
|
||||||
long i, end;
|
|
||||||
|
|
||||||
end = FIX2LONG(to);
|
|
||||||
for (i=FIX2LONG(from); i >= end; i--) {
|
|
||||||
rb_yield(LONG2FIX(i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
VALUE i = from, c;
|
|
||||||
|
|
||||||
while (!(c = rb_funcall(i, '<', 1, to))) {
|
|
||||||
rb_yield(i);
|
|
||||||
i = rb_funcall(i, '-', 1, INT2FIX(1));
|
|
||||||
}
|
|
||||||
if (NIL_P(c)) rb_cmperr(i, to);
|
|
||||||
}
|
|
||||||
return from;
|
|
||||||
}
|
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
int_dotimes_size(VALUE num, VALUE args, VALUE eobj)
|
int_dotimes_size(VALUE num, VALUE args, VALUE eobj)
|
||||||
{
|
{
|
||||||
|
@ -6246,7 +6202,6 @@ Init_Numeric(void)
|
||||||
rb_define_method(rb_cInteger, "anybits?", int_anybits_p, 1);
|
rb_define_method(rb_cInteger, "anybits?", int_anybits_p, 1);
|
||||||
rb_define_method(rb_cInteger, "nobits?", int_nobits_p, 1);
|
rb_define_method(rb_cInteger, "nobits?", int_nobits_p, 1);
|
||||||
rb_define_method(rb_cInteger, "upto", int_upto, 1);
|
rb_define_method(rb_cInteger, "upto", int_upto, 1);
|
||||||
rb_define_method(rb_cInteger, "downto", int_downto, 1);
|
|
||||||
rb_define_method(rb_cInteger, "succ", int_succ, 0);
|
rb_define_method(rb_cInteger, "succ", int_succ, 0);
|
||||||
rb_define_method(rb_cInteger, "next", int_succ, 0);
|
rb_define_method(rb_cInteger, "next", int_succ, 0);
|
||||||
rb_define_method(rb_cInteger, "pred", int_pred, 0);
|
rb_define_method(rb_cInteger, "pred", int_pred, 0);
|
||||||
|
|
29
numeric.rb
29
numeric.rb
|
@ -241,6 +241,35 @@ class Integer
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# call-seq:
|
||||||
|
# downto(limit) {|i| ... } -> self
|
||||||
|
# downto(limit) -> enumerator
|
||||||
|
#
|
||||||
|
# Calls the given block with each integer value from +self+ down to +limit+;
|
||||||
|
# returns +self+:
|
||||||
|
#
|
||||||
|
# a = []
|
||||||
|
# 10.downto(5) {|i| a << i } # => 10
|
||||||
|
# a # => [10, 9, 8, 7, 6, 5]
|
||||||
|
# a = []
|
||||||
|
# 0.downto(-5) {|i| a << i } # => 0
|
||||||
|
# a # => [0, -1, -2, -3, -4, -5]
|
||||||
|
# 4.downto(5) {|i| fail 'Cannot happen' } # => 4
|
||||||
|
#
|
||||||
|
# With no block given, returns an Enumerator.
|
||||||
|
def downto to
|
||||||
|
Primitive.attr! :inline_block
|
||||||
|
unless defined?(yield)
|
||||||
|
return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 1, &to, int_downto_size)'
|
||||||
|
end
|
||||||
|
|
||||||
|
from = self
|
||||||
|
while from >= to
|
||||||
|
yield from
|
||||||
|
from = from.pred
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# call-seq:
|
# call-seq:
|
||||||
# to_i -> self
|
# to_i -> self
|
||||||
#
|
#
|
||||||
|
|
Загрузка…
Ссылка в новой задаче