summaryrefslogtreecommitdiff
path: root/array.rb
diff options
context:
space:
mode:
authorAaron Patterson <[email protected]>2024-07-03 09:45:29 -0700
committerAaron Patterson <[email protected]>2024-07-03 11:32:40 -0700
commit4c9134d2b2ab3830dd4cca3b9595c97fc7361392 (patch)
tree80b49421107ee8df9031056f61e9e37c511168d0 /array.rb
parent7fe5f0a1d0e628e9e330169a5c2dedae0d40dedd (diff)
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 f4b313f733) [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 f4b313f733) +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. ```
Diffstat (limited to 'array.rb')
-rw-r--r--array.rb35
1 files changed, 35 insertions, 0 deletions
diff --git a/array.rb b/array.rb
index f63ff00056..5ec95a1097 100644
--- a/array.rb
+++ b/array.rb
@@ -57,6 +57,41 @@ class Array
end
# call-seq:
+ # array.select {|element| ... } -> new_array
+ # array.select -> new_enumerator
+ #
+ # Calls the block, if given, with each element of +self+;
+ # returns a new +Array+ containing those elements of +self+
+ # for which the block returns a truthy value:
+ #
+ # a = [:foo, 'bar', 2, :bam]
+ # a1 = a.select {|element| element.to_s.start_with?('b') }
+ # a1 # => ["bar", :bam]
+ #
+ # Returns a new Enumerator if no block given:
+ #
+ # a = [:foo, 'bar', 2, :bam]
+ # a.select # => #<Enumerator: [:foo, "bar", 2, :bam]:select>
+ def select
+ Primitive.attr! :inline_block
+ Primitive.attr! :use_block
+
+ unless defined?(yield)
+ return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)'
+ end
+
+ _i = 0
+ value = nil
+ result = Primitive.ary_sized_alloc
+ while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) })
+ result << value if yield value
+ end
+ result
+ end
+
+ alias filter select
+
+ # call-seq:
# array.shuffle!(random: Random) -> array
#
# Shuffles the elements of +self+ in place.