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:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b4dba673f286e0a526b602537257364dda4b7477eed8698d7f69a0993b3b0ff5
|
|
4
|
+
data.tar.gz: 344f0dd405e3249068746359edff5d9b1578bdf2bb736861f27548283f64d91d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
|
-
#
|
|
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:
|
|
25
|
-
timeout:
|
|
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
|
|
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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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
|
|
26
|
-
#
|
|
27
|
-
|
|
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
|
|