everythingrb 0.9.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -10
- data/README.md +79 -100
- data/Rakefile +24 -0
- data/benchmarks/array_benchmark.rb +108 -0
- data/benchmarks/benchmark_helper.rb +42 -0
- data/benchmarks/enumerable_benchmark.rb +80 -0
- data/benchmarks/hash_benchmark.rb +160 -0
- data/benchmarks/kernel_benchmark.rb +51 -0
- data/benchmarks/module_benchmark.rb +106 -0
- data/benchmarks/ostruct_benchmark.rb +84 -0
- data/benchmarks/quotable_benchmark.rb +111 -0
- data/benchmarks/run_all.rb +74 -0
- data/benchmarks/string_benchmark.rb +85 -0
- data/lib/everythingrb/array.rb +0 -45
- data/lib/everythingrb/data.rb +0 -19
- data/lib/everythingrb/date.rb +2 -0
- data/lib/everythingrb/hash.rb +7 -113
- data/lib/everythingrb/module.rb +79 -14
- data/lib/everythingrb/ostruct.rb +0 -20
- data/lib/everythingrb/string.rb +26 -52
- data/lib/everythingrb/struct.rb +0 -21
- data/lib/everythingrb/version.rb +1 -1
- metadata +12 -2
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "benchmark_helper"
|
|
4
|
+
|
|
5
|
+
BenchmarkHelper.header("Enumerable Extension Benchmarks")
|
|
6
|
+
|
|
7
|
+
# Test data - using Range as an Enumerable that isn't Array
|
|
8
|
+
small_range = 1..10
|
|
9
|
+
medium_range = 1..100
|
|
10
|
+
large_range = 1..1000
|
|
11
|
+
|
|
12
|
+
users = [
|
|
13
|
+
{name: "Alice", role: "admin"},
|
|
14
|
+
{name: "Bob", role: "user"},
|
|
15
|
+
{name: "Charlie", role: "admin"},
|
|
16
|
+
{name: "Diana", role: "user"},
|
|
17
|
+
{name: "Eve", role: "moderator"}
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
nested_data = [
|
|
21
|
+
{department: {name: "Sales"}, employee: "Alice"},
|
|
22
|
+
{department: {name: "IT"}, employee: "Bob"},
|
|
23
|
+
{department: {name: "Sales"}, employee: "Charlie"},
|
|
24
|
+
{department: {name: "HR"}, employee: "Diana"},
|
|
25
|
+
{department: {name: "IT"}, employee: "Eve"}
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
large_users = (1..1000).map { |i| {name: "User#{i}", role: %w[admin user moderator][i % 3]} }
|
|
29
|
+
|
|
30
|
+
# ============================================================================
|
|
31
|
+
# join_map benchmarks (on Range)
|
|
32
|
+
# ============================================================================
|
|
33
|
+
|
|
34
|
+
BenchmarkHelper.run("join_map - small range (1..10)") do |x|
|
|
35
|
+
x.report("join_map") { small_range.join_map(" | ") { |n| "num#{n}" if n.even? } }
|
|
36
|
+
x.report("join_map(with_index)") { small_range.join_map(", ", with_index: true) { |n, i| "#{i}:#{n}" } }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
BenchmarkHelper.run("join_map - medium range (1..100)") do |x|
|
|
40
|
+
x.report("join_map") { medium_range.join_map(" | ") { |n| "num#{n}" if n.even? } }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
BenchmarkHelper.run("join_map - large range (1..1000)") do |x|
|
|
44
|
+
x.report("join_map") { large_range.join_map(" | ") { |n| "num#{n}" if n.even? } }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# ============================================================================
|
|
48
|
+
# group_by_key benchmarks
|
|
49
|
+
# ============================================================================
|
|
50
|
+
|
|
51
|
+
BenchmarkHelper.run("group_by_key - single key") do |x|
|
|
52
|
+
x.report("group_by_key(:role)") { users.group_by_key(:role) }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
BenchmarkHelper.run("group_by_key - nested keys") do |x|
|
|
56
|
+
x.report("group_by_key(:department, :name)") { nested_data.group_by_key(:department, :name) }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
BenchmarkHelper.run("group_by_key - with block transformation") do |x|
|
|
60
|
+
x.report("group_by_key with upcase") { users.group_by_key(:role) { |role| role.upcase } }
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
BenchmarkHelper.run("group_by_key - large dataset (1000 elements)") do |x|
|
|
64
|
+
x.report("group_by_key(:role)") { large_users.group_by_key(:role) }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# ============================================================================
|
|
68
|
+
# Set as Enumerable
|
|
69
|
+
# ============================================================================
|
|
70
|
+
|
|
71
|
+
small_set = Set.new(1..10)
|
|
72
|
+
medium_set = Set.new(1..100)
|
|
73
|
+
|
|
74
|
+
BenchmarkHelper.run("join_map - Set (10 elements)") do |x|
|
|
75
|
+
x.report("join_map") { small_set.join_map(", ") { |n| "item#{n}" if n.odd? } }
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
BenchmarkHelper.run("join_map - Set (100 elements)") do |x|
|
|
79
|
+
x.report("join_map") { medium_set.join_map(", ") { |n| "item#{n}" if n.odd? } }
|
|
80
|
+
end
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "benchmark_helper"
|
|
4
|
+
|
|
5
|
+
BenchmarkHelper.header("Hash Extension Benchmarks")
|
|
6
|
+
|
|
7
|
+
# Test data
|
|
8
|
+
small_hash = {a: 1, b: 2, c: 3}
|
|
9
|
+
medium_hash = (1..100).each_with_object({}) { |i, h| h[:"key#{i}"] = i }
|
|
10
|
+
|
|
11
|
+
nested_hash = {
|
|
12
|
+
user: {
|
|
13
|
+
profile: {name: "Alice", age: 30},
|
|
14
|
+
settings: {theme: "dark", notifications: true}
|
|
15
|
+
},
|
|
16
|
+
meta: {created_at: "2024-01-01"}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
users_hash = {
|
|
20
|
+
alice: {name: "Alice", role: "admin"},
|
|
21
|
+
bob: {name: "Bob", role: "user"},
|
|
22
|
+
charlie: {name: "Charlie", role: "admin"}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
# ============================================================================
|
|
26
|
+
# join_map benchmarks
|
|
27
|
+
# ============================================================================
|
|
28
|
+
|
|
29
|
+
BenchmarkHelper.run("join_map - small hash (3 keys)") do |x|
|
|
30
|
+
x.report("join_map") { small_hash.join_map(", ") { |k, v| "#{k}=#{v}" } }
|
|
31
|
+
x.report("join_map(with_index)") { small_hash.join_map(", ", with_index: true) { |(k, v), i| "#{i}:#{k}=#{v}" } }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
BenchmarkHelper.run("join_map - medium hash (100 keys)") do |x|
|
|
35
|
+
x.report("join_map") { medium_hash.join_map(", ") { |k, v| "#{k}=#{v}" } }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# ============================================================================
|
|
39
|
+
# to_struct / to_ostruct / to_istruct benchmarks
|
|
40
|
+
# ============================================================================
|
|
41
|
+
|
|
42
|
+
BenchmarkHelper.run("to_struct - small hash") do |x|
|
|
43
|
+
x.report("to_struct") { small_hash.to_struct }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
BenchmarkHelper.run("to_ostruct - small hash") do |x|
|
|
47
|
+
x.report("to_ostruct") { small_hash.to_ostruct }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
BenchmarkHelper.run("to_istruct - small hash") do |x|
|
|
51
|
+
x.report("to_istruct") { small_hash.to_istruct }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
BenchmarkHelper.run("structure conversion - nested hash") do |x|
|
|
55
|
+
x.report("to_struct") { nested_hash.to_struct }
|
|
56
|
+
x.report("to_ostruct") { nested_hash.to_ostruct }
|
|
57
|
+
x.report("to_istruct") { nested_hash.to_istruct }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# ============================================================================
|
|
61
|
+
# transform_values with_key benchmarks
|
|
62
|
+
# ============================================================================
|
|
63
|
+
|
|
64
|
+
BenchmarkHelper.run("transform_values - small hash") do |x|
|
|
65
|
+
x.report("transform_values") { small_hash.transform_values { |v| v * 2 } }
|
|
66
|
+
x.report("transform_values(with_key)") { small_hash.transform_values(with_key: true) { |v, k| "#{k}:#{v * 2}" } }
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
BenchmarkHelper.run("transform_values - medium hash") do |x|
|
|
70
|
+
x.report("transform_values") { medium_hash.transform_values { |v| v * 2 } }
|
|
71
|
+
x.report("transform_values(with_key)") { medium_hash.transform_values(with_key: true) { |v, k| "#{k}:#{v * 2}" } }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# ============================================================================
|
|
75
|
+
# transform / transform! benchmarks
|
|
76
|
+
# ============================================================================
|
|
77
|
+
|
|
78
|
+
BenchmarkHelper.run("transform - small hash") do |x|
|
|
79
|
+
x.report("transform") { small_hash.transform { |k, v| [:"new_#{k}", v * 2] } }
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
BenchmarkHelper.run("transform - medium hash") do |x|
|
|
83
|
+
x.report("transform") { medium_hash.transform { |k, v| [:"new_#{k}", v * 2] } }
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# ============================================================================
|
|
87
|
+
# find_value / select_values benchmarks
|
|
88
|
+
# ============================================================================
|
|
89
|
+
|
|
90
|
+
BenchmarkHelper.run("find_value / select_values") do |x|
|
|
91
|
+
x.report("find_value") { users_hash.find_value { |_k, v| v[:role] == "admin" } }
|
|
92
|
+
x.report("select_values") { users_hash.select_values { |_k, v| v[:role] == "admin" } }
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# ============================================================================
|
|
96
|
+
# rename_key / rename_keys benchmarks
|
|
97
|
+
# ============================================================================
|
|
98
|
+
|
|
99
|
+
BenchmarkHelper.run("rename_key - small hash") do |x|
|
|
100
|
+
x.report("rename_key (ordered)") { small_hash.rename_key(:b, :middle) }
|
|
101
|
+
x.report("rename_key_unordered") { small_hash.rename_key_unordered(:b, :middle) }
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
BenchmarkHelper.run("rename_keys - small hash") do |x|
|
|
105
|
+
x.report("rename_keys") { small_hash.rename_keys(a: :first, c: :last) }
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
BenchmarkHelper.run("rename_key - medium hash") do |x|
|
|
109
|
+
x.report("rename_key (ordered)") { medium_hash.rename_key(:key50, :middle) }
|
|
110
|
+
x.report("rename_key_unordered") { medium_hash.rename_key_unordered(:key50, :middle) }
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# ============================================================================
|
|
114
|
+
# merge_if / merge_if_values benchmarks
|
|
115
|
+
# ============================================================================
|
|
116
|
+
|
|
117
|
+
other_hash = {d: 4, e: 5, f: nil}
|
|
118
|
+
|
|
119
|
+
BenchmarkHelper.run("merge_if / merge_if_values") do |x|
|
|
120
|
+
x.report("merge_if") { small_hash.merge_if(other_hash) { |_k, v| v&.even? } }
|
|
121
|
+
x.report("merge_if_values") { small_hash.merge_if_values(other_hash) { |v| v&.odd? } }
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# ============================================================================
|
|
125
|
+
# compact_merge benchmarks
|
|
126
|
+
# ============================================================================
|
|
127
|
+
|
|
128
|
+
hash_with_nils = {a: 1, b: nil, c: 3, d: nil}
|
|
129
|
+
|
|
130
|
+
BenchmarkHelper.run("compact_merge") do |x|
|
|
131
|
+
x.report("compact_merge") { small_hash.compact_merge(hash_with_nils) }
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# ============================================================================
|
|
135
|
+
# in_quotes benchmarks
|
|
136
|
+
# ============================================================================
|
|
137
|
+
|
|
138
|
+
BenchmarkHelper.run("in_quotes / with_quotes") do |x|
|
|
139
|
+
x.report("small hash in_quotes") { small_hash.in_quotes }
|
|
140
|
+
x.report("nested hash in_quotes") { nested_hash.in_quotes }
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# ============================================================================
|
|
144
|
+
# ActiveSupport-only benchmarks
|
|
145
|
+
# ============================================================================
|
|
146
|
+
|
|
147
|
+
if BenchmarkHelper.active_support?
|
|
148
|
+
BenchmarkHelper.run("deep_transform_values(with_key)") do |x|
|
|
149
|
+
x.report("deep_transform_values") { nested_hash.deep_transform_values { |v| v.to_s.upcase } }
|
|
150
|
+
x.report("deep_transform_values(with_key)") { nested_hash.deep_transform_values(with_key: true) { |v, k| "#{k}:#{v}" } }
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
hash_with_blanks = {a: 1, b: "", c: [], d: "present"}
|
|
154
|
+
|
|
155
|
+
BenchmarkHelper.run("compact_blank_merge") do |x|
|
|
156
|
+
x.report("compact_blank_merge") { small_hash.compact_blank_merge(hash_with_blanks) }
|
|
157
|
+
end
|
|
158
|
+
else
|
|
159
|
+
puts "\n[SKIPPED] ActiveSupport benchmarks - run with LOAD_ACTIVE_SUPPORT=true"
|
|
160
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "benchmark_helper"
|
|
4
|
+
|
|
5
|
+
BenchmarkHelper.header("Kernel Extension Benchmarks")
|
|
6
|
+
|
|
7
|
+
# Test data
|
|
8
|
+
number = 42
|
|
9
|
+
string = "hello"
|
|
10
|
+
hash = {name: "Alice", age: 30}
|
|
11
|
+
array = [1, 2, 3, 4, 5]
|
|
12
|
+
|
|
13
|
+
# ============================================================================
|
|
14
|
+
# morph benchmarks (alias for then/yield_self)
|
|
15
|
+
# ============================================================================
|
|
16
|
+
|
|
17
|
+
BenchmarkHelper.run("morph - simple transformation") do |x|
|
|
18
|
+
x.report("morph { * 2 }") { number.morph { |n| n * 2 } }
|
|
19
|
+
x.report("morph { upcase }") { string.morph { |s| s.upcase } }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
BenchmarkHelper.run("morph - chained transformations") do |x|
|
|
23
|
+
x.report("morph chain (2 steps)") do
|
|
24
|
+
number.morph { |n| n * 2 }.morph { |n| n.to_s }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
x.report("morph chain (3 steps)") do
|
|
28
|
+
string.morph { |s| s.upcase }.morph { |s| s.reverse }.morph { |s| s.chars }
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
BenchmarkHelper.run("morph - with hash") do |x|
|
|
33
|
+
x.report("morph hash transform") do
|
|
34
|
+
hash.morph { |h| h.transform_values(&:to_s) }
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
BenchmarkHelper.run("morph - with array") do |x|
|
|
39
|
+
x.report("morph array transform") do
|
|
40
|
+
array.morph { |a| a.map { |n| n * 2 } }.morph { |a| a.sum }
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# ============================================================================
|
|
45
|
+
# morph vs then (should be identical - they're aliases)
|
|
46
|
+
# ============================================================================
|
|
47
|
+
|
|
48
|
+
BenchmarkHelper.run("morph vs then (alias verification)") do |x|
|
|
49
|
+
x.report("morph") { number.morph { |n| n * 2 } }
|
|
50
|
+
x.report("then") { number.then { |n| n * 2 } }
|
|
51
|
+
end
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "benchmark_helper"
|
|
4
|
+
|
|
5
|
+
BenchmarkHelper.header("Module Extension Benchmarks")
|
|
6
|
+
|
|
7
|
+
# Define test classes with attr_predicate
|
|
8
|
+
class UserWithPredicate
|
|
9
|
+
attr_accessor :admin, :active, :verified
|
|
10
|
+
attr_predicate :admin, :active, :verified
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class TaskWithFrom
|
|
14
|
+
attr_accessor :started_at, :stopped_at
|
|
15
|
+
attr_predicate :started, from: :@started_at
|
|
16
|
+
attr_predicate :finished, from: :@stopped_at
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class JobWithMethodFrom
|
|
20
|
+
attr_accessor :error_messages
|
|
21
|
+
attr_predicate :errored, from: :error_messages
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
PersonStruct = Struct.new(:active, :name)
|
|
25
|
+
PersonStruct.attr_predicate(:active)
|
|
26
|
+
|
|
27
|
+
# Test data
|
|
28
|
+
user_true = UserWithPredicate.new.tap do |u|
|
|
29
|
+
u.admin = true
|
|
30
|
+
u.active = true
|
|
31
|
+
u.verified = true
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
user_false = UserWithPredicate.new.tap do |u|
|
|
35
|
+
u.admin = false
|
|
36
|
+
u.active = nil
|
|
37
|
+
u.verified = ""
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
task_started = TaskWithFrom.new.tap { |t| t.started_at = Time.now }
|
|
41
|
+
task_not_started = TaskWithFrom.new
|
|
42
|
+
|
|
43
|
+
job_errored = JobWithMethodFrom.new.tap { |j| j.error_messages = ["Error 1", "Error 2"] }
|
|
44
|
+
job_clean = JobWithMethodFrom.new.tap { |j| j.error_messages = [] }
|
|
45
|
+
|
|
46
|
+
person_active = PersonStruct.new(true, "Alice")
|
|
47
|
+
person_inactive = PersonStruct.new(false, "Bob")
|
|
48
|
+
|
|
49
|
+
# ============================================================================
|
|
50
|
+
# attr_predicate - basic usage benchmarks
|
|
51
|
+
# ============================================================================
|
|
52
|
+
|
|
53
|
+
BenchmarkHelper.run("attr_predicate - truthy values") do |x|
|
|
54
|
+
x.report("admin? (true)") { user_true.admin? }
|
|
55
|
+
x.report("active? (true)") { user_true.active? }
|
|
56
|
+
x.report("verified? (true)") { user_true.verified? }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
BenchmarkHelper.run("attr_predicate - falsy values") do |x|
|
|
60
|
+
x.report("admin? (false)") { user_false.admin? }
|
|
61
|
+
x.report("active? (nil)") { user_false.active? }
|
|
62
|
+
x.report("verified? (empty string)") { user_false.verified? }
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# ============================================================================
|
|
66
|
+
# attr_predicate - with from: option (ivar)
|
|
67
|
+
# ============================================================================
|
|
68
|
+
|
|
69
|
+
BenchmarkHelper.run("attr_predicate with from: @ivar") do |x|
|
|
70
|
+
x.report("started? (has value)") { task_started.started? }
|
|
71
|
+
x.report("started? (nil)") { task_not_started.started? }
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# ============================================================================
|
|
75
|
+
# attr_predicate - with from: option (method)
|
|
76
|
+
# ============================================================================
|
|
77
|
+
|
|
78
|
+
BenchmarkHelper.run("attr_predicate with from: method") do |x|
|
|
79
|
+
x.report("errored? (has errors)") { job_errored.errored? }
|
|
80
|
+
x.report("errored? (empty array)") { job_clean.errored? }
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# ============================================================================
|
|
84
|
+
# attr_predicate - with Struct
|
|
85
|
+
# ============================================================================
|
|
86
|
+
|
|
87
|
+
BenchmarkHelper.run("attr_predicate on Struct") do |x|
|
|
88
|
+
x.report("active? (true)") { person_active.active? }
|
|
89
|
+
x.report("active? (false)") { person_inactive.active? }
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# ============================================================================
|
|
93
|
+
# attr_predicate definition time (one-time cost)
|
|
94
|
+
# ============================================================================
|
|
95
|
+
|
|
96
|
+
BenchmarkHelper.run("attr_predicate definition time") do |x|
|
|
97
|
+
x.report("define single predicate") do
|
|
98
|
+
klass = Class.new { attr_accessor :test }
|
|
99
|
+
klass.attr_predicate(:test)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
x.report("define multiple predicates") do
|
|
103
|
+
klass = Class.new { attr_accessor :a, :b, :c }
|
|
104
|
+
klass.attr_predicate(:a, :b, :c)
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "benchmark_helper"
|
|
4
|
+
|
|
5
|
+
BenchmarkHelper.header("OpenStruct Extension Benchmarks")
|
|
6
|
+
|
|
7
|
+
# Test data
|
|
8
|
+
small_ostruct = OpenStruct.new(a: 1, b: 2, c: 3)
|
|
9
|
+
medium_ostruct = OpenStruct.new((1..20).each_with_object({}) { |i, h| h[:"attr#{i}"] = i })
|
|
10
|
+
ostruct_with_nil = OpenStruct.new(a: 1, b: nil, c: 3, d: nil, e: 5)
|
|
11
|
+
empty_ostruct = OpenStruct.new
|
|
12
|
+
|
|
13
|
+
# ============================================================================
|
|
14
|
+
# map / filter_map benchmarks
|
|
15
|
+
# ============================================================================
|
|
16
|
+
|
|
17
|
+
BenchmarkHelper.run("map - small OpenStruct (3 attributes)") do |x|
|
|
18
|
+
x.report("map") { small_ostruct.map { |k, v| [k, v * 2] } }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
BenchmarkHelper.run("map - medium OpenStruct (20 attributes)") do |x|
|
|
22
|
+
x.report("map") { medium_ostruct.map { |k, v| [k, v * 2] } }
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
BenchmarkHelper.run("filter_map - with nils") do |x|
|
|
26
|
+
x.report("filter_map") { ostruct_with_nil.filter_map { |k, v| v * 2 if v } }
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# ============================================================================
|
|
30
|
+
# join_map benchmarks
|
|
31
|
+
# ============================================================================
|
|
32
|
+
|
|
33
|
+
BenchmarkHelper.run("join_map - small OpenStruct") do |x|
|
|
34
|
+
x.report("join_map") { small_ostruct.join_map(", ") { |k, v| "#{k}=#{v}" } }
|
|
35
|
+
x.report("join_map (no block)") { small_ostruct.join_map(", ") }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
BenchmarkHelper.run("join_map - with nils") do |x|
|
|
39
|
+
x.report("join_map (filtering nils)") { ostruct_with_nil.join_map(" ") { |k, v| "#{k}-#{v}" if v } }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# ============================================================================
|
|
43
|
+
# each (alias for each_pair)
|
|
44
|
+
# ============================================================================
|
|
45
|
+
|
|
46
|
+
BenchmarkHelper.run("each - small OpenStruct") do |x|
|
|
47
|
+
x.report("each") do
|
|
48
|
+
result = []
|
|
49
|
+
small_ostruct.each { |k, v| result << [k, v] }
|
|
50
|
+
result
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# ============================================================================
|
|
55
|
+
# to_ostruct (identity method)
|
|
56
|
+
# ============================================================================
|
|
57
|
+
|
|
58
|
+
BenchmarkHelper.run("to_ostruct (identity)") do |x|
|
|
59
|
+
x.report("to_ostruct") { small_ostruct.to_ostruct }
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# ============================================================================
|
|
63
|
+
# in_quotes benchmarks
|
|
64
|
+
# ============================================================================
|
|
65
|
+
|
|
66
|
+
BenchmarkHelper.run("in_quotes / with_quotes") do |x|
|
|
67
|
+
x.report("small ostruct in_quotes") { small_ostruct.in_quotes }
|
|
68
|
+
x.report("medium ostruct in_quotes") { medium_ostruct.in_quotes }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
# ============================================================================
|
|
72
|
+
# ActiveSupport-only benchmarks
|
|
73
|
+
# ============================================================================
|
|
74
|
+
|
|
75
|
+
if BenchmarkHelper.active_support?
|
|
76
|
+
BenchmarkHelper.run("blank? / present?") do |x|
|
|
77
|
+
x.report("blank? (empty)") { empty_ostruct.blank? }
|
|
78
|
+
x.report("blank? (non-empty)") { small_ostruct.blank? }
|
|
79
|
+
x.report("present? (empty)") { empty_ostruct.present? }
|
|
80
|
+
x.report("present? (non-empty)") { small_ostruct.present? }
|
|
81
|
+
end
|
|
82
|
+
else
|
|
83
|
+
puts "\n[SKIPPED] ActiveSupport benchmarks - run with LOAD_ACTIVE_SUPPORT=true"
|
|
84
|
+
end
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "benchmark_helper"
|
|
4
|
+
|
|
5
|
+
BenchmarkHelper.header("Quotable Extension Benchmarks")
|
|
6
|
+
|
|
7
|
+
# Test data for InspectQuotable types
|
|
8
|
+
array_value = [1, 2, 3]
|
|
9
|
+
hash_value = {a: 1, b: 2}
|
|
10
|
+
true_value = true
|
|
11
|
+
false_value = false
|
|
12
|
+
nil_value = nil
|
|
13
|
+
numeric_int = 42
|
|
14
|
+
numeric_float = 3.14159
|
|
15
|
+
range_value = 1..10
|
|
16
|
+
regexp_value = /hello/
|
|
17
|
+
struct_value = Struct.new(:name, :age).new("Alice", 30)
|
|
18
|
+
|
|
19
|
+
# Test data for StringQuotable types
|
|
20
|
+
string_value = "hello world"
|
|
21
|
+
date_value = Date.new(2024, 1, 15)
|
|
22
|
+
datetime_value = DateTime.new(2024, 1, 15, 12, 30, 0)
|
|
23
|
+
time_value = Time.new(2024, 1, 15, 12, 30, 0)
|
|
24
|
+
|
|
25
|
+
# Symbol has its own implementation
|
|
26
|
+
symbol_value = :my_symbol
|
|
27
|
+
|
|
28
|
+
# ============================================================================
|
|
29
|
+
# InspectQuotable types
|
|
30
|
+
# ============================================================================
|
|
31
|
+
|
|
32
|
+
BenchmarkHelper.run("in_quotes - Array") do |x|
|
|
33
|
+
x.report("array.in_quotes") { array_value.in_quotes }
|
|
34
|
+
x.report("array.with_quotes") { array_value.with_quotes }
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
BenchmarkHelper.run("in_quotes - Hash") do |x|
|
|
38
|
+
x.report("hash.in_quotes") { hash_value.in_quotes }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
BenchmarkHelper.run("in_quotes - Boolean") do |x|
|
|
42
|
+
x.report("true.in_quotes") { true_value.in_quotes }
|
|
43
|
+
x.report("false.in_quotes") { false_value.in_quotes }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
BenchmarkHelper.run("in_quotes - NilClass") do |x|
|
|
47
|
+
x.report("nil.in_quotes") { nil_value.in_quotes }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
BenchmarkHelper.run("in_quotes - Numeric") do |x|
|
|
51
|
+
x.report("integer.in_quotes") { numeric_int.in_quotes }
|
|
52
|
+
x.report("float.in_quotes") { numeric_float.in_quotes }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
BenchmarkHelper.run("in_quotes - Range") do |x|
|
|
56
|
+
x.report("range.in_quotes") { range_value.in_quotes }
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
BenchmarkHelper.run("in_quotes - Regexp") do |x|
|
|
60
|
+
x.report("regexp.in_quotes") { regexp_value.in_quotes }
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
BenchmarkHelper.run("in_quotes - Struct") do |x|
|
|
64
|
+
x.report("struct.in_quotes") { struct_value.in_quotes }
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# ============================================================================
|
|
68
|
+
# StringQuotable types
|
|
69
|
+
# ============================================================================
|
|
70
|
+
|
|
71
|
+
BenchmarkHelper.run("in_quotes - String") do |x|
|
|
72
|
+
x.report("string.in_quotes") { string_value.in_quotes }
|
|
73
|
+
x.report("string.with_quotes") { string_value.with_quotes }
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
BenchmarkHelper.run("in_quotes - Date") do |x|
|
|
77
|
+
x.report("date.in_quotes") { date_value.in_quotes }
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
BenchmarkHelper.run("in_quotes - DateTime") do |x|
|
|
81
|
+
x.report("datetime.in_quotes") { datetime_value.in_quotes }
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
BenchmarkHelper.run("in_quotes - Time") do |x|
|
|
85
|
+
x.report("time.in_quotes") { time_value.in_quotes }
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# ============================================================================
|
|
89
|
+
# Symbol (custom implementation)
|
|
90
|
+
# ============================================================================
|
|
91
|
+
|
|
92
|
+
BenchmarkHelper.run("in_quotes - Symbol") do |x|
|
|
93
|
+
x.report("symbol.in_quotes") { symbol_value.in_quotes }
|
|
94
|
+
x.report("symbol.with_quotes") { symbol_value.with_quotes }
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
# ============================================================================
|
|
98
|
+
# All types comparison
|
|
99
|
+
# ============================================================================
|
|
100
|
+
|
|
101
|
+
BenchmarkHelper.run("in_quotes - all types comparison") do |x|
|
|
102
|
+
x.report("Array") { array_value.in_quotes }
|
|
103
|
+
x.report("Hash") { hash_value.in_quotes }
|
|
104
|
+
x.report("String") { string_value.in_quotes }
|
|
105
|
+
x.report("Symbol") { symbol_value.in_quotes }
|
|
106
|
+
x.report("Integer") { numeric_int.in_quotes }
|
|
107
|
+
x.report("nil") { nil_value.in_quotes }
|
|
108
|
+
x.report("true") { true_value.in_quotes }
|
|
109
|
+
x.report("Date") { date_value.in_quotes }
|
|
110
|
+
x.report("Time") { time_value.in_quotes }
|
|
111
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Run all EverythingRB benchmarks
|
|
5
|
+
#
|
|
6
|
+
# Usage:
|
|
7
|
+
# ruby benchmarks/run_all.rb # Run all benchmarks
|
|
8
|
+
# ruby benchmarks/run_all.rb array hash # Run specific benchmarks
|
|
9
|
+
# LOAD_ACTIVE_SUPPORT=true ruby benchmarks/run_all.rb # Include ActiveSupport benchmarks
|
|
10
|
+
#
|
|
11
|
+
# Available benchmarks:
|
|
12
|
+
# array, hash, string, enumerable, ostruct, module, kernel, quotable
|
|
13
|
+
|
|
14
|
+
BENCHMARK_DIR = File.expand_path(__dir__)
|
|
15
|
+
|
|
16
|
+
AVAILABLE_BENCHMARKS = %w[
|
|
17
|
+
array
|
|
18
|
+
hash
|
|
19
|
+
string
|
|
20
|
+
enumerable
|
|
21
|
+
ostruct
|
|
22
|
+
module
|
|
23
|
+
kernel
|
|
24
|
+
quotable
|
|
25
|
+
].freeze
|
|
26
|
+
|
|
27
|
+
def run_benchmark(name)
|
|
28
|
+
file = File.join(BENCHMARK_DIR, "#{name}_benchmark.rb")
|
|
29
|
+
|
|
30
|
+
if File.exist?(file)
|
|
31
|
+
load file
|
|
32
|
+
else
|
|
33
|
+
puts "Warning: Benchmark file not found: #{file}"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def print_header
|
|
38
|
+
puts
|
|
39
|
+
puts "#" * 70
|
|
40
|
+
puts "#" + "EverythingRB Benchmarks".center(68) + "#"
|
|
41
|
+
puts "#" * 70
|
|
42
|
+
puts
|
|
43
|
+
puts "Ruby version: #{RUBY_VERSION}"
|
|
44
|
+
puts "Platform: #{RUBY_PLATFORM}"
|
|
45
|
+
puts "ActiveSupport: #{(ENV["LOAD_ACTIVE_SUPPORT"] == "true") ? "loaded" : "not loaded"}"
|
|
46
|
+
puts
|
|
47
|
+
puts "Tip: Run with LOAD_ACTIVE_SUPPORT=true to include ActiveSupport benchmarks"
|
|
48
|
+
puts
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def print_footer
|
|
52
|
+
puts
|
|
53
|
+
puts "#" * 70
|
|
54
|
+
puts "#" + "Benchmarks Complete".center(68) + "#"
|
|
55
|
+
puts "#" * 70
|
|
56
|
+
puts
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Main execution
|
|
60
|
+
print_header
|
|
61
|
+
|
|
62
|
+
benchmarks_to_run = ARGV.empty? ? AVAILABLE_BENCHMARKS : ARGV
|
|
63
|
+
|
|
64
|
+
benchmarks_to_run.each do |benchmark|
|
|
65
|
+
if AVAILABLE_BENCHMARKS.include?(benchmark)
|
|
66
|
+
run_benchmark(benchmark)
|
|
67
|
+
else
|
|
68
|
+
puts "Unknown benchmark: #{benchmark}"
|
|
69
|
+
puts "Available benchmarks: #{AVAILABLE_BENCHMARKS.join(", ")}"
|
|
70
|
+
exit 1
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
print_footer
|