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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d942ece685b0dd024227075db9d16fa1d2cca81ee91921d3926814bd033d4c08
4
- data.tar.gz: dce496aed3eea5cb5448f515e5c029eab4e5ad744ce6bb41666f7525555e9cb9
3
+ metadata.gz: b72123961fe15e37146749930e0bd09d4d52a821c739a7ec662bc84976f9ac3b
4
+ data.tar.gz: 8fb581b9a516e6eaec6b664d19bb9354f115bfb61282c1a3cb289d1d72ac203c
5
5
  SHA512:
6
- metadata.gz: 57f467d74ec8c0f566549ab140935bd19d3b296f727be40f83c4da5c771da4b8594ed54d668ebca17a2937d64b3d2c80efedac2d48617bfcc1c2055886782a65
7
- data.tar.gz: 11902dda9958604c7c6770c4d43bb123b2f7e9a5f37187cfae73232a9d7ad8ef55fd3b38b360a597652d23ad4e5c2ff157f09aa646ec6005ac40567d7c9891af
6
+ metadata.gz: 63b8fdab356d3d60e2aa05f4e99df82da0617a988da5c92bf8ec430ed3016fa4e594c856ecfc0f03d9aee42bc63a365e54dc254014614124bd851339e6962ac9
7
+ data.tar.gz: 96d310ed31f7ce0476a824c6a086ec5acbe4fa4cdfa5e9282b285a4dec9133f41997e5f534e07eb537a2d67b5c1a46b4e258aba2c97f491ac0088b131a407477
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rails_benchmark_suite (0.2.2)
4
+ rails_benchmark_suite (0.2.6)
5
5
  actionview (~> 8.1)
6
6
  activerecord (~> 8.1)
7
7
  activestorage (~> 8.1)
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
- Run via bundle:
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
- # Senior Fix: Isolate from host application's database with Shared Cache (v0.2.5)
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::memory:?cache=shared",
23
+ database: "file:heft_db?mode=memory&cache=shared",
22
24
  pool: 16,
23
- timeout: 5000
25
+ timeout: 10000
24
26
  )
25
27
 
26
- # SQLite Performance Tuning for multi-threaded benchmarks
27
- raw_db = ActiveRecord::Base.connection.raw_connection
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
- # Add a custom busy handler for extra resilience (v0.2.5)
32
- raw_db.busy_handler { |count| sleep(0.01); count < 100 }
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
- # Load Schema
35
- RailsBenchmarkSuite::Schema.load
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
- "System: Ruby #{info[:ruby_version]} (#{info[:platform]}), #{info[:processors]} Cores. YJIT: #{info[:yjit] ? 'Enabled' : 'Disabled'}. Libvips: #{info[:libvips]}"
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
- ActiveRecord::Base.transaction do
10
- # 1. Create
11
- user = RailsBenchmarkSuite::Models::User.create!(name: "Speedy Gonzales", email: "speedy@example.com")
12
-
13
- # 2. Create associated records (simulate some weight)
14
- 10.times do |i|
15
- user.posts.create!(title: "Post #{i}", body: "Content " * 50)
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
@@ -1,3 +1,3 @@
1
1
  module RailsBenchmarkSuite
2
- VERSION = "0.2.5"
2
+ VERSION = "0.2.7"
3
3
  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.5
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.5.22
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: []