rails_benchmark_suite 0.2.5 → 0.2.7
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/Gemfile.lock +1 -1
- data/README.md +63 -2
- data/lib/rails_benchmark_suite/runner.rb +22 -12
- data/lib/rails_benchmark_suite/suites/active_record_suite.rb +33 -21
- data/lib/rails_benchmark_suite/version.rb +1 -1
- metadata +2 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b72123961fe15e37146749930e0bd09d4d52a821c739a7ec662bc84976f9ac3b
|
|
4
|
+
data.tar.gz: 8fb581b9a516e6eaec6b664d19bb9354f115bfb61282c1a3cb289d1d72ac203c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 63b8fdab356d3d60e2aa05f4e99df82da0617a988da5c92bf8ec430ed3016fa4e594c856ecfc0f03d9aee42bc63a365e54dc254014614124bd851339e6962ac9
|
|
7
|
+
data.tar.gz: 96d310ed31f7ce0476a824c6a086ec5acbe4fa4cdfa5e9282b285a4dec9133f41997e5f534e07eb537a2d67b5c1a46b4e258aba2c97f491ac0088b131a407477
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -28,6 +28,10 @@ Rails Benchmark Suite prioritizes **Benchmarking** (via `benchmark-ips`) over **
|
|
|
28
28
|
|
|
29
29
|
## 🚀 Installation & Usage
|
|
30
30
|
|
|
31
|
+
### Requirements
|
|
32
|
+
- **Ruby**: 3.3+ (Ruby with YJIT support highly recommended for accurate performance measurement)
|
|
33
|
+
- **Database**: SQLite3
|
|
34
|
+
|
|
31
35
|
### Prerequisites
|
|
32
36
|
* **Ruby:** 3.4.1+ (Recommended for latest YJIT/Prism performance)
|
|
33
37
|
* **Database:** SQLite3
|
|
@@ -51,14 +55,71 @@ Add to your Gemfile:
|
|
|
51
55
|
gem "rails_benchmark_suite", group: :development
|
|
52
56
|
```
|
|
53
57
|
|
|
54
|
-
|
|
58
|
+
## Usage
|
|
59
|
+
|
|
60
|
+
To get the most accurate 'Heft' score, run with YJIT enabled:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
ruby --yjit -S bundle exec rails_benchmark_suite
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Why these flags?**
|
|
67
|
+
- `--yjit`: Enables the Ruby JIT compiler (significant for Rails 8+ performance).
|
|
68
|
+
- `-S`: Corrects the path to look for the executable in your current bundle.
|
|
69
|
+
- `bundle exec`: Prevents version conflicts (e.g., Minitest) between the gem and your host application.
|
|
70
|
+
|
|
71
|
+
**Standalone Usage:**
|
|
72
|
+
If running outside a Rails project:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
bin/rails_benchmark_suite
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**JSON Output:**
|
|
79
|
+
For programmatic consumption:
|
|
55
80
|
|
|
56
81
|
```bash
|
|
57
|
-
bundle exec rails_benchmark_suite
|
|
82
|
+
ruby --yjit -S bundle exec rails_benchmark_suite --json
|
|
58
83
|
```
|
|
59
84
|
|
|
60
85
|
> **Note:** Use `--skip-rails` to ignore the host application and run in isolated mode.
|
|
61
86
|
|
|
87
|
+
## Performance
|
|
88
|
+
|
|
89
|
+
**Understanding YJIT Status:**
|
|
90
|
+
|
|
91
|
+
If you see `YJIT: Disabled`, this is a result of your Ruby binary build, not the gem itself. The gem will work perfectly fine without YJIT, but performance measurements will be more accurate with YJIT enabled.
|
|
92
|
+
|
|
93
|
+
To enable YJIT, you need Ruby compiled with YJIT support (requires Rust compiler during Ruby installation). See the Troubleshooting section below for installation instructions.
|
|
94
|
+
|
|
95
|
+
## Troubleshooting
|
|
96
|
+
|
|
97
|
+
### YJIT Shows "Disabled"
|
|
98
|
+
|
|
99
|
+
If you see `YJIT: Disabled (Requires Ruby with YJIT support for best results)`, it means your Ruby was not compiled with YJIT support. To get the best performance:
|
|
100
|
+
|
|
101
|
+
1. Ensure `rustc` (Rust compiler) is installed on your system
|
|
102
|
+
2. Reinstall Ruby with YJIT support:
|
|
103
|
+
```bash
|
|
104
|
+
# Using rbenv
|
|
105
|
+
RUBY_CONFIGURE_OPTS="--enable-yjit" rbenv install 3.4.1
|
|
106
|
+
|
|
107
|
+
# Using rvm
|
|
108
|
+
rvm install 3.4.1 --enable-yjit
|
|
109
|
+
```
|
|
110
|
+
3. Verify YJIT is available: `ruby --yjit -e "puts RubyVM::YJIT.enabled?"`
|
|
111
|
+
|
|
112
|
+
### SQLite Lock Errors
|
|
113
|
+
|
|
114
|
+
If you encounter `SQLite3::BusyException` or "database table is locked" errors, ensure you're running the latest version of the gem (v0.2.7+) which includes automatic concurrency retries with smart backoff.
|
|
115
|
+
|
|
116
|
+
**v0.2.7+** includes:
|
|
117
|
+
- Automatic retry logic with sleep backoff
|
|
118
|
+
- Per-thread unique identifiers to prevent conflicts
|
|
119
|
+
- Optimized busy timeout settings (10 seconds)
|
|
120
|
+
|
|
121
|
+
If issues persist, try reducing concurrency or ensuring no other processes are accessing the benchmark database.
|
|
122
|
+
|
|
62
123
|
## 🏗 Architecture
|
|
63
124
|
* **Engine:** Built on `benchmark-ips`.
|
|
64
125
|
* **Database:** Uses In-Memory SQLite with `cache=shared` for multi-threaded accuracy.
|
|
@@ -14,25 +14,30 @@ module RailsBenchmarkSuite
|
|
|
14
14
|
@suites << { name: name, block: block }
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
+
SETUP_MUTEX = Mutex.new
|
|
18
|
+
|
|
17
19
|
def run
|
|
18
|
-
#
|
|
20
|
+
# Hardened Isolation: Shared Cache URI for multi-threading (v0.2.7)
|
|
19
21
|
ActiveRecord::Base.establish_connection(
|
|
20
22
|
adapter: "sqlite3",
|
|
21
|
-
database: "file
|
|
23
|
+
database: "file:heft_db?mode=memory&cache=shared",
|
|
22
24
|
pool: 16,
|
|
23
|
-
timeout:
|
|
25
|
+
timeout: 10000
|
|
24
26
|
)
|
|
25
27
|
|
|
26
|
-
#
|
|
27
|
-
|
|
28
|
-
raw_db.execute("PRAGMA journal_mode = WAL") # Write-Ahead Logging
|
|
29
|
-
raw_db.execute("PRAGMA synchronous = NORMAL") # Faster writes
|
|
28
|
+
# The 'Busy Timeout' Hammer - force it directly on the raw connection
|
|
29
|
+
ActiveRecord::Base.connection.raw_connection.busy_timeout = 10000
|
|
30
30
|
|
|
31
|
-
#
|
|
32
|
-
|
|
31
|
+
# Setup Schema once safely with Mutex
|
|
32
|
+
SETUP_MUTEX.synchronize do
|
|
33
|
+
# Verify if schema already loaded by checking for a table
|
|
34
|
+
unless ActiveRecord::Base.connection.table_exists?(:users)
|
|
35
|
+
RailsBenchmarkSuite::Schema.load
|
|
36
|
+
end
|
|
37
|
+
end
|
|
33
38
|
|
|
34
|
-
#
|
|
35
|
-
|
|
39
|
+
# High-Performance Pragmas
|
|
40
|
+
ActiveRecord::Base.connection.raw_connection.execute("PRAGMA synchronous = OFF")
|
|
36
41
|
|
|
37
42
|
puts "Running RailsBenchmarkSuite Benchmarks..." unless @json_output
|
|
38
43
|
puts system_report unless @json_output
|
|
@@ -92,7 +97,12 @@ module RailsBenchmarkSuite
|
|
|
92
97
|
|
|
93
98
|
def system_report
|
|
94
99
|
info = RailsBenchmarkSuite::Reporter.system_info
|
|
95
|
-
|
|
100
|
+
yjit_status = if defined?(RubyVM::YJIT) && RubyVM::YJIT.enabled?
|
|
101
|
+
"Enabled"
|
|
102
|
+
else
|
|
103
|
+
"Disabled (Requires Ruby with YJIT support for best results)"
|
|
104
|
+
end
|
|
105
|
+
"System: Ruby #{info[:ruby_version]} (#{info[:platform]}), #{info[:processors]} Cores. YJIT: #{yjit_status}. Libvips: #{info[:libvips]}"
|
|
96
106
|
end
|
|
97
107
|
|
|
98
108
|
def print_summary(results)
|
|
@@ -6,27 +6,39 @@ require "active_record"
|
|
|
6
6
|
RailsBenchmarkSuite.register_suite("Active Record Heft", weight: 0.4) do
|
|
7
7
|
# Workload: Create User with Posts, Join Query, Update
|
|
8
8
|
# Use transaction rollback to keep the DB clean and avoid costly destroy callbacks
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
begin
|
|
10
|
+
ActiveRecord::Base.transaction do
|
|
11
|
+
# 1. Create - with unique email per thread
|
|
12
|
+
user = RailsBenchmarkSuite::Models::User.create!(
|
|
13
|
+
name: "Benchmark User",
|
|
14
|
+
email: "test-#{Thread.current.object_id}@example.com"
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
# 2. Create associated records (simulate some weight)
|
|
18
|
+
10.times do |i|
|
|
19
|
+
user.posts.create!(title: "Post #{i}", body: "Content " * 50)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# 3. Complex Query (Join + Order)
|
|
23
|
+
# Unloading the relation to force execution
|
|
24
|
+
RailsBenchmarkSuite::Models::User.joins(:posts)
|
|
25
|
+
.where(users: { id: user.id })
|
|
26
|
+
.where("posts.views >= ?", 0)
|
|
27
|
+
.order("posts.created_at DESC")
|
|
28
|
+
.to_a
|
|
29
|
+
|
|
30
|
+
# 4. Update
|
|
31
|
+
user.update!(name: "Updated User")
|
|
32
|
+
|
|
33
|
+
# Rollback everything to leave the DB clean for next iteration
|
|
34
|
+
raise ActiveRecord::Rollback
|
|
35
|
+
end
|
|
36
|
+
rescue ActiveRecord::StatementInvalid => e
|
|
37
|
+
if e.message =~ /locked/i
|
|
38
|
+
sleep(0.005)
|
|
39
|
+
retry
|
|
40
|
+
else
|
|
41
|
+
raise e
|
|
16
42
|
end
|
|
17
|
-
|
|
18
|
-
# 3. Complex Query (Join + Order)
|
|
19
|
-
# Unloading the relation to force execution
|
|
20
|
-
RailsBenchmarkSuite::Models::User.joins(:posts)
|
|
21
|
-
.where(users: { id: user.id })
|
|
22
|
-
.where("posts.views >= ?", 0)
|
|
23
|
-
.order("posts.created_at DESC")
|
|
24
|
-
.to_a
|
|
25
|
-
|
|
26
|
-
# 4. Update
|
|
27
|
-
user.update!(name: "Slowpoke Rodriguez")
|
|
28
|
-
|
|
29
|
-
# Rollback everything to leave the DB clean for next iteration
|
|
30
|
-
raise ActiveRecord::Rollback
|
|
31
43
|
end
|
|
32
44
|
end
|
metadata
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rails_benchmark_suite
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.7
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- RailsBenchmarkSuite Contributors
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
10
|
date: 2026-01-02 00:00:00.000000000 Z
|
|
@@ -204,7 +203,6 @@ metadata:
|
|
|
204
203
|
source_code_uri: https://github.com/overnet/rails_benchmark_suite
|
|
205
204
|
bug_tracker_uri: https://github.com/overnet/rails_benchmark_suite/issues
|
|
206
205
|
changelog_uri: https://github.com/overnet/rails_benchmark_suite/blob/main/CHANGELOG.md
|
|
207
|
-
post_install_message:
|
|
208
206
|
rdoc_options: []
|
|
209
207
|
require_paths:
|
|
210
208
|
- lib
|
|
@@ -219,8 +217,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
219
217
|
- !ruby/object:Gem::Version
|
|
220
218
|
version: '0'
|
|
221
219
|
requirements: []
|
|
222
|
-
rubygems_version: 3.
|
|
223
|
-
signing_key:
|
|
220
|
+
rubygems_version: 3.6.2
|
|
224
221
|
specification_version: 4
|
|
225
222
|
summary: Rails-style functionality & performance benchmark tool
|
|
226
223
|
test_files: []
|