rails_benchmark_suite 0.2.6 → 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: c0ba63e3d45287127a9fe0b288163f0d7bc8e0620a03ef2c9659732a6785e60f
4
- data.tar.gz: 98e7c9a9cb433203ccb4cdaa07435753c7c696ee8dadc2df81d5b2e3b651cf94
3
+ metadata.gz: b72123961fe15e37146749930e0bd09d4d52a821c739a7ec662bc84976f9ac3b
4
+ data.tar.gz: 8fb581b9a516e6eaec6b664d19bb9354f115bfb61282c1a3cb289d1d72ac203c
5
5
  SHA512:
6
- metadata.gz: 8c801578bae53257e375fb058ad14015785851bd1def663b1a52c5d271cc243e0af74746e96ffcc007b17f5fdcc5df414d010686e02c35a1816746fff93f23b5
7
- data.tar.gz: 1216ba6595a80999820713962e2e41b01e94ccd662379a3b6c07334c0f2301e1ddd9588bf36f6354f3a958049f2c6ddd95f2280bd18802917d4df974efacdbfe
6
+ metadata.gz: 63b8fdab356d3d60e2aa05f4e99df82da0617a988da5c92bf8ec430ed3016fa4e594c856ecfc0f03d9aee42bc63a365e54dc254014614124bd851339e6962ac9
7
+ data.tar.gz: 96d310ed31f7ce0476a824c6a086ec5acbe4fa4cdfa5e9282b285a4dec9133f41997e5f534e07eb537a2d67b5c1a46b4e258aba2c97f491ac0088b131a407477
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,17 +55,9 @@ Add to your Gemfile:
51
55
  gem "rails_benchmark_suite", group: :development
52
56
  ```
53
57
 
54
- ## Quick Start
55
-
56
- For the best performance measurement with YJIT enabled:
57
-
58
- ```bash
59
- ruby --yjit -S bundle exec rails_benchmark_suite
60
- ```
61
-
62
58
  ## Usage
63
59
 
64
- To get the most accurate 'Heft' score within a Rails project context, run:
60
+ To get the most accurate 'Heft' score, run with YJIT enabled:
65
61
 
66
62
  ```bash
67
63
  ruby --yjit -S bundle exec rails_benchmark_suite
@@ -88,6 +84,42 @@ ruby --yjit -S bundle exec rails_benchmark_suite --json
88
84
 
89
85
  > **Note:** Use `--skip-rails` to ignore the host application and run in isolated mode.
90
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
+
91
123
  ## 🏗 Architecture
92
124
  * **Engine:** Built on `benchmark-ips`.
93
125
  * **Database:** Uses In-Memory SQLite with `cache=shared` for multi-threaded accuracy.
@@ -17,17 +17,16 @@ module RailsBenchmarkSuite
17
17
  SETUP_MUTEX = Mutex.new
18
18
 
19
19
  def run
20
- # Hardened Isolation: In-memory Shared Cache URI (v0.2.6)
20
+ # Hardened Isolation: Shared Cache URI for multi-threading (v0.2.7)
21
21
  ActiveRecord::Base.establish_connection(
22
22
  adapter: "sqlite3",
23
23
  database: "file:heft_db?mode=memory&cache=shared",
24
- pool: 20,
24
+ pool: 16,
25
25
  timeout: 10000
26
26
  )
27
27
 
28
- # Explicit Busy Timeout (Critical for multi-threading)
29
- raw_db = ActiveRecord::Base.connection.raw_connection
30
- raw_db.busy_timeout = 10000
28
+ # The 'Busy Timeout' Hammer - force it directly on the raw connection
29
+ ActiveRecord::Base.connection.raw_connection.busy_timeout = 10000
31
30
 
32
31
  # Setup Schema once safely with Mutex
33
32
  SETUP_MUTEX.synchronize do
@@ -37,9 +36,8 @@ module RailsBenchmarkSuite
37
36
  end
38
37
  end
39
38
 
40
- # High-Performance Concurrency Pragmas
41
- raw_db.execute("PRAGMA journal_mode = WAL")
42
- raw_db.execute("PRAGMA synchronous = OFF")
39
+ # High-Performance Pragmas
40
+ ActiveRecord::Base.connection.raw_connection.execute("PRAGMA synchronous = OFF")
43
41
 
44
42
  puts "Running RailsBenchmarkSuite Benchmarks..." unless @json_output
45
43
  puts system_report unless @json_output
@@ -99,8 +97,12 @@ module RailsBenchmarkSuite
99
97
 
100
98
  def system_report
101
99
  info = RailsBenchmarkSuite::Reporter.system_info
102
- yjit_status = !!(defined?(RubyVM::YJIT) && RubyVM::YJIT.enabled?)
103
- "System: Ruby #{info[:ruby_version]} (#{info[:platform]}), #{info[:processors]} Cores. YJIT: #{yjit_status ? '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]}"
104
106
  end
105
107
 
106
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.6"
2
+ VERSION = "0.2.7"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails_benchmark_suite
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.6
4
+ version: 0.2.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - RailsBenchmarkSuite Contributors