1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

array.c: improve operations on small arrays

[Feature #13884]

Reduce number of memory allocations for "and", "or" and "diff"
operations on small arrays

Very often, arrays are used to filter parameters and to select
interesting items from 2 collections and very often these
collections are small enough, for example:

```ruby
SAFE_COLUMNS = [:id, :title, :created_at]

def columns
  @all_columns & SAFE_COLUMNS
end
```

In this patch, I got rid of unnecessary memory allocations for
small arrays when "and", "or" and "diff" operations are performed.

name             | HEAD  | PATCH
-----------------+------:+------:
array_small_and  | 0.615 | 0.263
array_small_diff | 0.676 | 0.282
array_small_or   | 0.953 | 0.463

name             | PATCH
-----------------+------:
array_small_and  | 2.343
array_small_diff | 2.392
array_small_or   | 2.056

name             | HEAD  | PATCH
-----------------+------:+------:
array_small_and  | 1.429 | 1.005
array_small_diff | 1.493 | 0.878
array_small_or   | 1.672 | 1.152

name             | PATCH
-----------------+------:
array_small_and  | 1.422
array_small_diff | 1.700
array_small_or   | 1.452

Author:    Dmitry Bochkarev <dimabochkarev@gmail.com>

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60057 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2017-09-29 07:43:22 +00:00
parent ff6573b696
commit 9bc73cd81f
8 changed files with 163 additions and 17 deletions

View file

@ -45,8 +45,8 @@ describe "Array#|" do
obj1 = mock('1')
obj2 = mock('2')
obj1.should_receive(:hash).at_least(1).and_return(0)
obj2.should_receive(:hash).at_least(1).and_return(0)
obj1.stub!(:hash).and_return(0)
obj2.stub!(:hash).and_return(0)
obj2.should_receive(:eql?).at_least(1).and_return(true)
([obj1] | [obj2]).should == [obj1]
@ -54,8 +54,8 @@ describe "Array#|" do
obj1 = mock('3')
obj2 = mock('4')
obj1.should_receive(:hash).at_least(1).and_return(0)
obj2.should_receive(:hash).at_least(1).and_return(0)
obj1.stub!(:hash).and_return(0)
obj2.stub!(:hash).and_return(0)
obj2.should_receive(:eql?).at_least(1).and_return(false)
([obj1] | [obj2]).should == [obj1, obj2]
@ -74,7 +74,7 @@ describe "Array#|" do
it "properly handles an identical item even when its #eql? isn't reflexive" do
x = mock('x')
x.should_receive(:hash).at_least(1).and_return(42)
x.stub!(:hash).and_return(42)
x.stub!(:eql?).and_return(false) # Stubbed for clarity and latitude in implementation; not actually sent by MRI.
([x] | [x]).should == [x]