8000 Move Array#select to Ruby · ruby/ruby@4c9134d · GitHub
[go: up one dir, main page]

Skip to content

Commit 4c9134d

Browse files
committed
Move Array#select to Ruby
This speeds up the mail benchmark by about 7% on the interpreter: ``` before: ruby 3.4.0dev (2024-07-03T17:01:41Z master f4b313f) [arm64-darwin23] after: ruby 3.4.0dev (2024-07-03T17:45:50Z ruby-select de282cacd5) [arm64-darwin23] ----- ----------- ---------- ---------- ---------- ------------- ------------ bench before (ms) stddev (%) after (ms) stddev (%) after 1st itr before/after mail 72.9 0.8 68.2 1.0 1.02 1.07 ----- ----------- ---------- ---------- ---------- ------------- ------------ 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 about 13% faster: ``` before: ruby 3.4.0dev (2024-07-03T17:01:41Z master f4b313f) +YJIT [arm64-darwin23] after: ruby 3.4.0dev (2024-07-03T17:45:50Z ruby-select de282cacd5) +YJIT [arm64-darwin23] ----- ----------- ---------- ---------- ---------- ------------- ------------ bench before (ms) stddev (%) after (ms) stddev (%) after 1st itr before/after mail 51.0 0.8 45.2 0.6 1.00 1.13 ----- ----------- ---------- ---------- ---------- ------------- ------------ 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. ```
1 parent 7fe5f0a commit 4c9134d

File tree

2 files changed

+41
-38
lines changed

2 files changed

+41
-38
lines changed

array.c

Lines changed: 6 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3807,42 +3807,6 @@ rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
38073807
}
38083808

38093809

3810-
/*
3811-
* call-seq:
3812-
* array.select {|element| ... } -> new_array
3813-
* array.select -> new_enumerator
3814-
*
3815-
* Calls the block, if given, with each element of +self+;
3816-
* returns a new +Array+ containing those elements of +self+
3817-
* for which the block returns a truthy value:
3818-
*
3819-
* a = [:foo, 'bar', 2, :bam]
3820-
* a1 = a.select {|element| element.to_s.start_with?('b') }
3821-
* a1 # => ["bar", :bam]
3822-
*
3823-
* Returns a new Enumerator if no block given:
3824-
*
3825-
* a = [:foo, 'bar', 2, :bam]
3826-
* a.select # => #<Enumerator: [:foo, "bar", 2, :bam]:select>
3827-
*
3828-
*/
3829-
3830-
static VALUE
3831-
rb_ary_select(VALUE ary)
3832-
{
3833-
VALUE result;
3834-
long i;
3835-
3836-
RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
3837-
result = rb_ary_new2(RARRAY_LEN(ary));
3838-
for (i = 0; i < RARRAY_LEN(ary); i++) {
3839-
if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
3840-
rb_ary_push(result, rb_ary_elt(ary, i));
3841-
}
3842-
}
3843-
return result;
3844-
}
3845-
38463810
struct select_bang_arg {
38473811
VALUE ary;
38483812
long len[2];
@@ -6696,6 +6660,12 @@ ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE
66966660
return result;
66976661
}
66986662

6663+
static VALUE
6664+
ary_sized_alloc(rb_execution_context_t *ec, VALUE self)
6665+
{
6666+
return rb_ary_new2(RARRAY_LEN(self));
6667+
}
6668+
66996669
static VALUE
67006670
ary_sample0(rb_execution_context_t *ec, VALUE ary)
67016671
{
@@ -8702,9 +8672,7 @@ Init_Array(void)
87028672
rb_define_method(rb_cArray, "collect!", rb_ary_collect_bang, 0);
87038673
rb_define_method(rb_cArray, "map", rb_ary_collect, 0);
87048674
rb_define_method(rb_cArray, "map!", rb_ary_collect_bang, 0);
8705-
rb_define_method(rb_cArray, "select", rb_ary_select, 0);
87068675
rb_define_method(rb_cArray, "select!", rb_ary_select_bang, 0);
8707-
rb_define_method(rb_cArray, "filter", rb_ary_select, 0);
87088676
rb_define_method(rb_cArray, "filter!", rb_ary_select_bang, 0);
87098677
rb_define_method(rb_cArray, "keep_if", rb_ary_keep_if, 0);
87108678
rb_define_method(rb_cArray, "values_at", rb_ary_values_at, -1);

array.rb

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,41 @@ def each
5656
self
5757
end
5858

59+
# call-seq:
60+
# array.select {|element| ... } -> new_array
61+
# array.select -> new_enumerator
62+
#
63+
# Calls the block, if given, with each element of +self+;
64+
# returns a new +Array+ containing those elements of +self+
65+
# for which the block returns a truthy value:
66+
#
67+
# a = [:foo, 'bar', 2, :bam]
68+
# a1 = a.select {|element| element.to_s.start_with?('b') }
69+
# a1 # => ["bar", :bam]
70+
#
71+
# Returns a new Enumerator if no block given:
72+
#
73+
# a = [:foo, 'bar', 2, :bam]
74+
# a.select # => #<Enumerator: [:foo, "bar", 2, :bam]:select>
75+
def select
76+
Primitive.attr! :inline_block
77+
Primitive.attr! :use_block
78+
79+
unless defined?(yield)
80+
return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)'
81+
end
82+
83+
_i = 0
84+
value = nil
85+
result = Primitive.ary_sized_alloc
86+
while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) })
87+
result << value if yield value
88+
end
89+
result
90+
end
91+
92+
alias filter select
93+
5994
# call-seq:
6095
# array.shuffle!(random: Random) -> array
6196
#

0 commit comments

Comments
 (0)
0