rails_benchmark_suite 0.2.7 → 0.2.8

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: b72123961fe15e37146749930e0bd09d4d52a821c739a7ec662bc84976f9ac3b
4
- data.tar.gz: 8fb581b9a516e6eaec6b664d19bb9354f115bfb61282c1a3cb289d1d72ac203c
3
+ metadata.gz: b4dba673f286e0a526b602537257364dda4b7477eed8698d7f69a0993b3b0ff5
4
+ data.tar.gz: 344f0dd405e3249068746359edff5d9b1578bdf2bb736861f27548283f64d91d
5
5
  SHA512:
6
- metadata.gz: 63b8fdab356d3d60e2aa05f4e99df82da0617a988da5c92bf8ec430ed3016fa4e594c856ecfc0f03d9aee42bc63a365e54dc254014614124bd851339e6962ac9
7
- data.tar.gz: 96d310ed31f7ce0476a824c6a086ec5acbe4fa4cdfa5e9282b285a4dec9133f41997e5f534e07eb537a2d67b5c1a46b4e258aba2c97f491ac0088b131a407477
6
+ metadata.gz: 65ae4cd0975954f2d7ccb3e5b60d25c587eb76d7ea3d3bfc771b1e879c6ccf5b6749b823323506973c500c49c415b2050b12bacdc7b497fc4d3e9791c1ac9943
7
+ data.tar.gz: d1af906dc1e84f78d92b74c27f74156aa8fd25d92016a317d342a084f5657bc72d2eb2f6b6e10a822e46073c71f886a1563e8f52d2ee5f68764b5e68c41a4a35
data/README.md CHANGED
@@ -19,6 +19,12 @@ The Heft Score is a weighted metric representing a machine's ability to handle R
19
19
  | 150+ | 🚀 High Performance | Apple M-series Pro/Max, Ryzen 5000+ |
20
20
  | 300+ | ⚡ Blazing | Server-grade Metal, M3 Ultra |
21
21
 
22
+ ### Quick Start
23
+ ```bash
24
+ ruby --yjit -S bundle exec rails_benchmark_suite
25
+ ```
26
+ **Note:** `bundle exec` is required for Rails environment stability and to prevent Minitest version conflicts.
27
+
22
28
  ## 🛠 Technical Philosophy
23
29
 
24
30
  Rails Benchmark Suite prioritizes **Benchmarking** (via `benchmark-ips`) over **Profiling**.
@@ -17,12 +17,12 @@ module RailsBenchmarkSuite
17
17
  SETUP_MUTEX = Mutex.new
18
18
 
19
19
  def run
20
- # Hardened Isolation: Shared Cache URI for multi-threading (v0.2.7)
20
+ # Ultimate Hardening: Massive pool and timeout for zero lock contention (v0.2.8)
21
21
  ActiveRecord::Base.establish_connection(
22
22
  adapter: "sqlite3",
23
23
  database: "file:heft_db?mode=memory&cache=shared",
24
- pool: 16,
25
- timeout: 10000
24
+ pool: 50,
25
+ timeout: 30000
26
26
  )
27
27
 
28
28
  # The 'Busy Timeout' Hammer - force it directly on the raw connection
@@ -36,8 +36,10 @@ module RailsBenchmarkSuite
36
36
  end
37
37
  end
38
38
 
39
- # High-Performance Pragmas
40
- ActiveRecord::Base.connection.raw_connection.execute("PRAGMA synchronous = OFF")
39
+ # High-Performance Pragmas for WAL + NORMAL sync
40
+ ActiveRecord::Base.connection.raw_connection.execute("PRAGMA journal_mode = WAL")
41
+ ActiveRecord::Base.connection.raw_connection.execute("PRAGMA synchronous = NORMAL")
42
+ ActiveRecord::Base.connection.raw_connection.execute("PRAGMA mmap_size = 268435456") # 256MB - reduce disk I/O
41
43
 
42
44
  puts "Running RailsBenchmarkSuite Benchmarks..." unless @json_output
43
45
  puts system_report unless @json_output
@@ -57,7 +59,7 @@ module RailsBenchmarkSuite
57
59
 
58
60
  # Single Threaded
59
61
  x.report("#{suite[:name]} (1 thread)") do
60
- suite[:block].call
62
+ with_retries { suite[:block].call }
61
63
  end
62
64
 
63
65
  # Multi Threaded (4 threads)
@@ -66,7 +68,7 @@ module RailsBenchmarkSuite
66
68
  Thread.new do
67
69
  # Ensure each thread gets a dedicated connection
68
70
  ActiveRecord::Base.connection_pool.with_connection do
69
- suite[:block].call
71
+ with_retries { suite[:block].call }
70
72
  end
71
73
  end
72
74
  end
@@ -95,6 +97,19 @@ module RailsBenchmarkSuite
95
97
 
96
98
  private
97
99
 
100
+ def with_retries
101
+ yield
102
+ rescue ActiveRecord::StatementInvalid => e
103
+ if e.message =~ /locked/i
104
+ # Specifically drop the lock for THIS connection only
105
+ ActiveRecord::Base.connection.reset!
106
+ sleep(rand(0.01..0.05))
107
+ retry
108
+ else
109
+ raise e
110
+ end
111
+ end
112
+
98
113
  def system_report
99
114
  info = RailsBenchmarkSuite::Reporter.system_info
100
115
  yjit_status = if defined?(RubyVM::YJIT) && RubyVM::YJIT.enabled?
@@ -6,39 +6,30 @@ 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
- 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
9
+ ActiveRecord::Base.transaction do
10
+ # 1. Create - with unique email per thread
11
+ user = RailsBenchmarkSuite::Models::User.create!(
12
+ name: "Benchmark User",
13
+ email: "test-#{Thread.current.object_id}@example.com"
14
+ )
15
+
16
+ # 2. Create associated records (simulate some weight)
17
+ 10.times do |i|
18
+ user.posts.create!(title: "Post #{i}", body: "Content " * 50)
42
19
  end
20
+
21
+ # 3. Complex Query (Join + Order)
22
+ # Unloading the relation to force execution
23
+ RailsBenchmarkSuite::Models::User.joins(:posts)
24
+ .where(users: { id: user.id })
25
+ .where("posts.views >= ?", 0)
26
+ .order("posts.created_at DESC")
27
+ .to_a
28
+
29
+ # 4. Update
30
+ user.update!(name: "Updated User")
31
+
32
+ # Rollback everything to leave the DB clean for next iteration
33
+ raise ActiveRecord::Rollback
43
34
  end
44
35
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Check if vips is available at registration time
3
4
  begin
4
5
  require "image_processing/vips"
5
6
  require "fileutils"
@@ -9,6 +10,7 @@ begin
9
10
  FileUtils.mkdir_p(ASSET_DIR)
10
11
  SAMPLE_IMAGE = File.join(ASSET_DIR, "sample.jpg")
11
12
 
13
+ # Only register if vips is actually available
12
14
  RailsBenchmarkSuite.register_suite("Image Heft", weight: 0.1) do
13
15
  # Gracefully handle missing dependencies
14
16
  if File.exist?(SAMPLE_IMAGE)
@@ -22,13 +24,8 @@ begin
22
24
  end
23
25
  end
24
26
 
25
- rescue LoadError, StandardError => e
26
- # Register a skipped suite if Libvips is unavailable
27
- RailsBenchmarkSuite.register_suite("Image Heft (Skipped)", weight: 0.0) do
28
- @warned ||= begin
29
- warn "⚠️ [RailsBenchmarkSuite] ImageHeft skipped: #{e.message}. Install libvips to enable."
30
- true
31
- end
32
- end
27
+ rescue LoadError, StandardError
28
+ # Don't register the suite at all if vips is unavailable
29
+ puts "⚠️ Skipping Image Heft: libvips not available. Install with: brew install vips (macOS)"
33
30
  end
34
31
 
@@ -1,3 +1,3 @@
1
1
  module RailsBenchmarkSuite
2
- VERSION = "0.2.7"
2
+ VERSION = "0.2.8"
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.7
4
+ version: 0.2.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - RailsBenchmarkSuite Contributors