Skip to content

Commit 8d394e0

Browse files
committed
Add ActiveSupport and faster implementation
1 parent 90750df commit 8d394e0

File tree

3 files changed

+66
-30
lines changed

3 files changed

+66
-30
lines changed

README.md

+17-8
Original file line numberDiff line numberDiff line change
@@ -937,24 +937,33 @@ Comparison:
937937
sort + to_h: 81972.8 i/s - 1.49x slower
938938
```
939939

940-
##### `Hash#slice` vs `Hash#select{ includes? }` [code](code/hash/slice-vs-select-include.rb)
940+
##### Native `Hash#slice` vs other slice implementations before native
941+
[code](code/hash/slice-native-vs-before-native.rb)
941942

942943
Since ruby 2.5, Hash comes with a `slice` method to select hash members by keys.
943944

944945
```
945-
$ ruby code/hash/slice-vs-select-include.rb
946+
$ ruby -v code/hash/slice-native-vs-before-native.rb
946947
ruby 2.5.3p105 (2018-10-18 revision 65156) [x86_64-linux]
947-
948+
Warming up --------------------------------------
949+
Hash#native-slice 178.077k i/100ms
950+
Array#each 124.311k i/100ms
951+
Array#each_w/_object 110.818k i/100ms
952+
Hash#select-include 66.972k i/100ms
948953
Calculating -------------------------------------
949-
Hash#slice 3.124M (± 0.6%) i/s - 15.675M in 5.017984s
950-
Hash#select_if_includes
951-
1.342M (± 1.1%) i/s - 6.716M in 5.003901s
954+
Hash#native-slice 2.540M (± 1.5%) i/s - 12.822M in 5.049955s
955+
Array#each 1.614M (± 1.0%) i/s - 8.080M in 5.007925s
956+
Array#each_w/_object 1.353M (± 2.6%) i/s - 6.760M in 5.000441s
957+
Hash#select-include 760.944k (± 0.9%) i/s - 3.817M in 5.017123s
952958
953959
Comparison:
954-
Hash#slice: 3123803.2 i/s
955-
Hash#select_if_includes: 1342270.6 i/s - 2.33x slower
960+
Hash#native-slice : 2539515.5 i/s
961+
Array#each : 1613665.5 i/s - 1.57x slower
962+
Array#each_w/_object: 1352851.8 i/s - 1.88x slower
963+
Hash#select-include : 760944.2 i/s - 3.34x slower
956964
```
957965

966+
958967
### Proc & Block
959968

960969
##### Block vs `Symbol#to_proc` [code](code/proc-and-block/block-vs-to_proc.rb)
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
require 'benchmark/ips'
2+
3+
HASH = {
4+
title: "awesome",
5+
description: "a description",
6+
author: "styd",
7+
published_at: Time.now
8+
}
9+
10+
HASH.dup.each{ |k, v| HASH[:"other_#{k}"], HASH[:"more_#{k}"] = v, v }
11+
12+
# Native implementation since v2.5
13+
#
14+
def fastest
15+
HASH.slice(*%i[title author other])
16+
end
17+
18+
# @ixti's faster implementation than that of ActiveSupport below
19+
#
20+
# Source:
21+
# https://github.com/JuanitoFatas/fast-ruby/pull/173#issuecomment-470554483
22+
#
23+
def faster
24+
memo = {}
25+
%i[title author other].each { |k| memo[k] = HASH[k] if HASH.key?(k) }
26+
memo
27+
end
28+
29+
# ActiveSupport implementation of `slice` when it's not defined.
30+
#
31+
# Source:
32+
# https://github.com/rails/rails/blob/01ae39660243bc5f0a986e20f9c9bff312b1b5f8/activesupport/lib/active_support/core_ext/hash/slice.rb#L24
33+
#
34+
def fast
35+
%i[title author other].each_with_object({}){ |k, h| h[k] = HASH[k] if HASH.key?(k) }
36+
end
37+
38+
def slow
39+
keys = %i[title author other]
40+
HASH.select { |k, _| keys.include? k }
41+
end
42+
43+
Benchmark.ips do |x|
44+
x.report('Hash#native-slice ') { fastest }
45+
x.report('Array#each ') { faster }
46+
x.report('Array#each_w/_object') { fast }
47+
x.report('Hash#select-include ') { slow }
48+
x.compare!
49+
end

code/hash/slice-vs-select-include.rb

-22
This file was deleted.

0 commit comments

Comments
 (0)