rails_benchmark_suite 0.2.9 → 0.3.1

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.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -1
  3. data/CHANGELOG.md +65 -0
  4. data/Gemfile.lock +29 -1
  5. data/README.md +103 -10
  6. data/bin/rails_benchmark_suite +35 -12
  7. data/docs/images/report_v0_3_1.png +0 -0
  8. data/lib/dummy/app/models/benchmark_job.rb +7 -0
  9. data/lib/dummy/app/models/benchmark_post.rb +9 -0
  10. data/lib/dummy/app/models/benchmark_user.rb +9 -0
  11. data/lib/dummy/app/views/rails_benchmark_suite/heft_view.html.erb +11 -0
  12. data/lib/dummy/config/benchmark_database.yml +16 -0
  13. data/lib/rails_benchmark_suite/configuration.rb +22 -0
  14. data/lib/rails_benchmark_suite/database_manager.rb +56 -0
  15. data/lib/rails_benchmark_suite/db_setup.rb +3 -0
  16. data/lib/rails_benchmark_suite/models/user.rb +4 -3
  17. data/lib/rails_benchmark_suite/reporter.rb +215 -5
  18. data/lib/rails_benchmark_suite/reporters/html_reporter.rb +52 -0
  19. data/lib/rails_benchmark_suite/runner.rb +46 -191
  20. data/lib/rails_benchmark_suite/schema.rb +5 -5
  21. data/lib/rails_benchmark_suite/templates/report.html.erb +187 -0
  22. data/lib/rails_benchmark_suite/version.rb +1 -1
  23. data/lib/rails_benchmark_suite/workload_runner.rb +158 -0
  24. data/lib/rails_benchmark_suite/{suites/active_record_suite.rb → workloads/active_record_workload.rb} +7 -7
  25. data/lib/rails_benchmark_suite/{suites/cache_heft_suite.rb → workloads/cache_heft_workload.rb} +2 -2
  26. data/lib/rails_benchmark_suite/{suites/image_heft_suite.rb → workloads/image_heft_workload.rb} +3 -4
  27. data/lib/rails_benchmark_suite/{suites/job_heft_suite.rb → workloads/job_heft_workload.rb} +4 -4
  28. data/lib/rails_benchmark_suite/workloads/view_heft_workload.rb +36 -0
  29. data/lib/rails_benchmark_suite.rb +3 -22
  30. data/rails_benchmark_suite.gemspec +7 -2
  31. metadata +92 -10
  32. data/lib/rails_benchmark_suite/suites/view_heft_suite.rb +0 -44
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c48ce5faaa5348bcd47cdd9c88ba9b1441d0f7bcd0a6fa601d84b36014673d1a
4
- data.tar.gz: f39f188c55fe6749a5b9ba4ae9c5c44e926bd5d6588737f689192ab841deda92
3
+ metadata.gz: 473aa21869380dae81d4f9ee8668ccf161721923fd6c453cc711caf9d6303fd1
4
+ data.tar.gz: 5101bb8d63885263dc3fcbb8851d52f3ed48a1f919b0abfab38d43dc3f3df2a2
5
5
  SHA512:
6
- metadata.gz: 28f32ff03be6cbd83aabb1c3f8750316f5c3e2cb69de127885f96a4ef27841b12ee916999c2dea59c314605a6755f0aee34d0c610338c596bbff2789120a7ce0
7
- data.tar.gz: 2e4f5a17c66e0caed9a95a46cdc3e0049783eea603f9cd263d699f492d49440f7ceaab45bf4c469b8b05fc316ca999052d12705dfe29b0edf54b032160fc2966
6
+ metadata.gz: 11311aa76df4c103c8b3ea2e12a803ddeb339cd454127b246557341ddd5c7872fa01c4ff00f4c14ae711d95b48f0d84b148ec7f8b0a39fda7ab70cac0d070bad
7
+ data.tar.gz: 3f141277e2daae966aa4d7d7be684e112889fa757282e36a4f35ac34d60ac91ca76903281d9e091b9549ef567d6e8b7a26b13221326bf8273c3c33fe7e6082fc
data/.gitignore CHANGED
@@ -1,5 +1,7 @@
1
- *.gem
1
+
2
2
  .bundle/
3
3
  vendor/bundle/
4
4
  Gemfile.lock
5
5
  .ruby-lsp/
6
+ *.gem
7
+ rails_benchmark_report.html
data/CHANGELOG.md CHANGED
@@ -1,4 +1,69 @@
1
1
  # Changelog
2
+ ## [0.3.1] - 2026-01-04
3
+ *Major Architectural Repair & TTY Overhaul*
4
+
5
+ ### Added
6
+ - **--html**: Static HTML Reporter with Chart.js visualization.
7
+ - **--profile**: Automated "Scaling Efficiency" calculation (1T vs MaxT).
8
+ - **--db**: Real database integration (Postgres/MySQL support).
9
+ - **Hardware Awareness**: Auto-detection of CPU cores for thread defaults.
10
+ - **UI**: Rich terminal output using `tty-spinner`, `tty-table`, and `tty-box` for a dashboard-style report.
11
+ - **Architecture**: Implemented the standard `lib/dummy` Rails Engine pattern for internal tests.
12
+
13
+ ### Changed
14
+ - **Refactor**: Complete structural overhaul. Moved monolithic logic from `lib/rails_benchmark_suite.rb` into a proper namespace (`lib/rails_benchmark_suite/`).
15
+ - **Concurrency**: Default thread count is now dynamic (`Etc.nprocessors`) instead of hardcoded to 4.
16
+ - **Safety**: Renamed internal test model from `User` to `BenchmarkUser` to prevent collisions when running inside host apps.
17
+
18
+ ### Fixed
19
+ - **CLI**: Fixed the non-functional `--help` flag (now implemented via `OptionParser`).
20
+ - **Reporting**: Restored the "Scaling (x)" column in the final report to correctly visualize performance degradation.
21
+
22
+ ## [0.3.0] - 2025-01-03
23
+
24
+ ### Major Architectural Refactor (SRP)
25
+ - **Runner Split**: Dismantled the monolithic `Runner` class (260+ lines) into three specialized modules:
26
+ - `DatabaseManager`: Handles ActiveRecord connection, schema loading, and SQLite PRAGMA optimizations
27
+ - `WorkloadRunner`: Manages benchmark execution engine with BASE_WEIGHTS normalization and complete payload generation
28
+ - `Formatter`: Centralized UI rendering, ANSI colors, insights engine, and output formatting
29
+ - **Runner Coordinator**: `Runner` is now a minimal 23-line coordinator delegating to the three modules
30
+
31
+ ### Normalized RHI Math Engine
32
+ - **BASE_WEIGHTS**: Defined workload weights (Active Record: 0.4, View: 0.2, Solid Queue: 0.2, Cache: 0.1, Image: 0.1)
33
+ - **Dynamic Weight Redistribution**: When workloads are skipped (e.g., missing libvips), weights are normalized proportionally to maintain 100% scale
34
+ - **Formula**: `RHI Score = Σ (4T_IPS × Adjusted_Weight)` where adjusted weights always sum to 1.0
35
+
36
+ ### Performance Insights Engine
37
+ - **Scaling Analysis**: Warns when multi-threading scaling < 0.8x, indicating SQLite lock contention or Ruby GIL saturation
38
+ - **YJIT Detection**: Displays hint to enable YJIT when disabled (typical 15-25% boost)
39
+ - **Memory Monitoring**: Alerts when workload memory growth exceeds 20MB, suggesting heavy object allocation
40
+ - **Hardware Tiering**: Provides comparison labels (Entry/Dev < 50, Production-Ready 50-200, High-Performance > 200)
41
+
42
+ ### UI/UX Enhancements
43
+ - **Box Alignment**: Fixed header and final score boxes with proper text length calculation (60-char width)
44
+ - **Table Spacing**: Added separator line between progress logs and results table for better readability
45
+ - **Insights Display**: Integrated insights below summary table with emoji indicators (💡, 📊)
46
+ - **Enhanced Number Formatting**: Smart k/M suffixes for readability (e.g., "15.3k", "1.2M")
47
+ - **YJIT Hints**: Helpful reminder `(run with RUBY_OPT="--yjit" for max perf)` when YJIT is disabled
48
+ - Silent migrations: Added `ActiveRecord::Migration.verbose = false` to reduce noise
49
+ - Cross-platform install instructions for libvips (macOS and Linux)
50
+
51
+ ### 🐛 Fixes
52
+ - Fixed `.gitignore` to properly track `gemspec` file for gem distribution
53
+ - **JSON Guard**: Ensures clean JSON output without any UI noise when `--json` flag is used
54
+ - Improved CLI output suppression in JSON mode
55
+
56
+ ### 📖 Documentation
57
+ - **Calculation Formula**: Added "How It's Calculated" section with RHI formula: `Σ (4-Thread IPS × Weight)`
58
+ - **Workload Weights Table**: Documented weights (Active Record 40%, View 20%, Jobs 20%, Cache 10%, Image 10%)
59
+ - **Hardware Tiers**: Explained tier classification system
60
+ - Complete README rewrite with four execution methods:
61
+ - Standard: `bundle exec rails_benchmark_suite`
62
+ - High Performance: `RUBY_OPT="--yjit" bundle exec rails_benchmark_suite`
63
+ - JSON Export: `bundle exec rails_benchmark_suite --json > report.json`
64
+ - Standalone: `bin/rails_benchmark_suite`
65
+ - Added comprehensive System Requirements section
66
+ - Updated all terminology from "Suite" to "Workload"
2
67
 
3
68
  ## [0.2.0] - 2025-12-31
4
69
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rails_benchmark_suite (0.2.6)
4
+ rails_benchmark_suite (0.3.1)
5
5
  actionview (~> 8.1)
6
6
  activerecord (~> 8.1)
7
7
  activestorage (~> 8.1)
@@ -9,7 +9,11 @@ PATH
9
9
  concurrent-ruby (~> 1.3)
10
10
  get_process_mem (~> 1.0)
11
11
  image_processing (~> 1.14)
12
+ pastel (~> 0.8)
12
13
  sqlite3 (~> 2.8)
14
+ tty-box (~> 0.7)
15
+ tty-spinner (~> 0.9)
16
+ tty-table (~> 0.12)
13
17
 
14
18
  GEM
15
19
  remote: https://rubygems.org/
@@ -116,6 +120,9 @@ GEM
116
120
  racc (~> 1.4)
117
121
  nokogiri (1.19.0-x86_64-linux-musl)
118
122
  racc (~> 1.4)
123
+ ostruct (0.6.3)
124
+ pastel (0.8.0)
125
+ tty-color (~> 0.5)
119
126
  racc (1.8.1)
120
127
  rack (3.2.4)
121
128
  rack-session (2.1.1)
@@ -145,9 +152,29 @@ GEM
145
152
  sqlite3 (2.9.0-x86_64-darwin)
146
153
  sqlite3 (2.9.0-x86_64-linux-gnu)
147
154
  sqlite3 (2.9.0-x86_64-linux-musl)
155
+ strings (0.2.1)
156
+ strings-ansi (~> 0.2)
157
+ unicode-display_width (>= 1.5, < 3.0)
158
+ unicode_utils (~> 1.4)
159
+ strings-ansi (0.2.0)
148
160
  timeout (0.6.0)
161
+ tty-box (0.7.0)
162
+ pastel (~> 0.8)
163
+ strings (~> 0.2.0)
164
+ tty-cursor (~> 0.7)
165
+ tty-color (0.6.0)
166
+ tty-cursor (0.7.1)
167
+ tty-screen (0.8.2)
168
+ tty-spinner (0.9.3)
169
+ tty-cursor (~> 0.7)
170
+ tty-table (0.12.0)
171
+ pastel (~> 0.8)
172
+ strings (~> 0.2.0)
173
+ tty-screen (~> 0.8)
149
174
  tzinfo (2.0.6)
150
175
  concurrent-ruby (~> 1.0)
176
+ unicode-display_width (2.6.0)
177
+ unicode_utils (1.4.0)
151
178
  uri (1.1.1)
152
179
  useragent (0.16.11)
153
180
 
@@ -166,6 +193,7 @@ PLATFORMS
166
193
  DEPENDENCIES
167
194
  bundler (~> 2.5)
168
195
  minitest (~> 5.0)
196
+ ostruct (~> 0.6)
169
197
  rails_benchmark_suite!
170
198
  rake (~> 13.0)
171
199
 
data/README.md CHANGED
@@ -26,6 +26,19 @@ The Heft Score is a weighted metric representing a machine's ability to handle R
26
26
  | **150+** | 🚀 High Performance | Apple M-series Pro/Max, Ryzen 5000+ |
27
27
  | **300+** | ⚡ Blazing | Server-grade Metal, M3 Ultra |
28
28
 
29
+ ### 📊 Visual Reports (HTML)
30
+
31
+ Visualize your threading efficiency and bottlenecks with a self-contained dashboard:
32
+
33
+ ```bash
34
+ bundle exec rails_benchmark_suite -t 8 --html
35
+ ```
36
+
37
+ This generates `rails_benchmark_report.html` containing:
38
+ - **Scaling Curve**: Interactive bar chart comparing 1-thread vs Max-thread throughput.
39
+ - **Efficiency Heatmap**: Score cards identifying which workloads are Gil-bound vs CPU-bound.
40
+ - **Detailed Metrics**: Raw IPS and detailed scaling factors.
41
+
29
42
  ---
30
43
 
31
44
  ## 🚀 Quick Start
@@ -56,19 +69,67 @@ Rails Benchmark Suite prioritizes **Benchmarking** (via `benchmark-ips`) over **
56
69
  * **Rails:** 8.1+
57
70
  * **Database:** SQLite3
58
71
 
59
- ### Use within a Rails Application
72
+ ## 📋 System Requirements
73
+
74
+ ### Required
75
+ - **Ruby**: 3.3+ (3.4+ recommended for YJIT)
76
+ - **Rails**: 8.0+
77
+ - **Database**: SQLite3
78
+
79
+ ### Optional (for Image Heft workload)
80
+ - **macOS**: `brew install vips`
81
+ - **Linux (Ubuntu/Debian)**: `sudo apt install libvips-dev`
82
+
83
+ ---
84
+
85
+ ## 🚀 Usage
86
+
87
+ ### Standard Execution
88
+ ```bash
89
+ bundle exec rails_benchmark_suite
90
+ ```
91
+ The easy way - run the benchmark with your current Ruby configuration.
92
+
93
+ ### High Performance (Recommended)
94
+ ```bash
95
+ RUBY_OPT="--yjit" bundle exec rails_benchmark_suite
96
+ ```
97
+ Enable YJIT for maximum performance measurement accuracy. This is the recommended method for Rails 8+ benchmarking.
98
+
99
+ ### JSON Export (Automation)
100
+ ```bash
101
+ bundle exec rails_benchmark_suite --json > report.json
102
+ ```
103
+ Perfect for CI/CD pipelines and programmatic analysis. Outputs clean JSON without any UI elements.
104
+
105
+ ### 📊 Visual Diagnostics (HTML Report)
106
+
107
+ ![Rails Benchmark Suite Report](docs/images/report_v0_3_1.png)
60
108
 
61
- Add to your Gemfile:
109
+ To diagnose scaling bottlenecks, run the tool in Profile Mode (`--profile`) and generate the HTML Report (`--html`). This compares Single-Thread vs Multi-Thread performance side-by-side.
62
110
 
63
- ```ruby
64
- gem "rails_benchmark_suite", group: :development
111
+ ```bash
112
+ bundle exec rails_benchmark_suite --profile --html
65
113
  ```
66
114
 
67
- ### Usage Flags
68
- * `--yjit`: Enables the Ruby JIT compiler (significant for Rails 8+ performance).
69
- * `-S`: Corrects the path to look for the executable in your current bundle.
70
- * `--json`: For programmatic consumption of results.
71
- * `--skip-rails`: To ignore the host application and run in isolated mode.
115
+ **Opening the Report**:
116
+ - **Local:** `open tmp/rails_benchmark_report.html`
117
+ - **Remote:** `scp user@server:/current/path/tmp/rails_benchmark_report.html .`
118
+
119
+ ### Command Line Options
120
+
121
+ | Flag | Description |
122
+ | :--- | :--- |
123
+ | `--html` | Generates a visual dashboard (`tmp/rails_benchmark_report.html`). **Best used with `--profile`.** |
124
+ | `--profile` | **Diagnostic Mode.** Runs the benchmark twice (1 Thread vs Max Threads) to calculate "Scaling Efficiency." Required to populate the "Scaling Curve" charts. |
125
+ | `--db` | Uses your local `config/database.yml` (Postgres/MySQL) instead of the synthetic in-memory SQLite. |
126
+ | `-t [N]` | Manually set the thread count (Default: Auto-detects CPU cores). |
127
+
128
+ ### Configuration Flags
129
+ - `--json`: Output results in JSON format
130
+ - `--skip-rails`: Run in isolated mode without loading Rails environment
131
+ - `--version`: Display gem version
132
+ - `-h` / `--help`: Show usage help
72
133
 
73
134
  ### Standalone Usage
74
135
 
@@ -83,7 +144,39 @@ bin/rails_benchmark_suite
83
144
 
84
145
  ---
85
146
 
86
- ## 🧪 The "Heft" Suites
147
+ ## 📐 How It's Calculated
148
+
149
+ The **Rails Heft Index (RHI)** measures your hardware's ability to handle Rails workloads using this formula:
150
+
151
+ ```
152
+ RHI Score = Σ (4-Thread IPS × Weight)
153
+ ```
154
+
155
+ ### Workload Weights
156
+
157
+ | Workload | Weight | Rationale |
158
+ |----------|--------|-----------|
159
+ | **Active Record** | 40% | Database operations are the core of most Rails apps |
160
+ | **View Rendering** | 20% | ERB/ActionView processing |
161
+ | **Solid Queue** | 20% | Background job throughput |
162
+ | **Cache Operations** | 10% | Memory store performance |
163
+ | **Image Processing** | 10% | Optional - requires libvips |
164
+
165
+ **Why 4-Thread IPS?** We use 4-thread performance to simulate production concurrency where multiple requests are handled simultaneously.
166
+
167
+ **Dynamic Weight Redistribution:** If a workload is skipped (e.g., Image Processing without libvips), its weight is redistributed proportionally among remaining workloads to maintain a 100% scale.
168
+
169
+ ### Hardware Tiers
170
+
171
+ Your RHI score maps to these performance tiers:
172
+
173
+ - **< 50**: Entry/Dev - Suitable for local development
174
+ - **50-200**: Production-Ready - Handles moderate production traffic
175
+ - **> 200**: High-Performance - Optimized for high-traffic applications
176
+
177
+ ---
178
+
179
+ ## 🧪 The "Heft" Workloads
87
180
 
88
181
  The gem measures performance across critical Rails subsystems using a dedicated, isolated schema:
89
182
 
@@ -2,11 +2,13 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require "optparse"
5
+ require "etc"
5
6
  $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
6
7
  require "rails_benchmark_suite"
7
8
  require "rails_benchmark_suite/version"
8
9
 
9
- options = {}
10
+ config = RailsBenchmarkSuite::Configuration.new
11
+
10
12
  OptionParser.new do |opts|
11
13
  opts.banner = "Usage: rails_benchmark_suite [options]"
12
14
 
@@ -15,12 +17,28 @@ OptionParser.new do |opts|
15
17
  exit 0
16
18
  end
17
19
 
20
+ opts.on("-t", "--threads N", Integer, "Number of threads (default: auto set to #{Etc.nprocessors} cores)") do |n|
21
+ config.threads = n
22
+ end
23
+
24
+ opts.on("-p", "--profile", "Enable scaling efficiency profile mode") do
25
+ config.profile = true
26
+ end
27
+
28
+ opts.on("-d", "--db", "Use real database from config/database.yml instead of in-memory SQLite") do
29
+ config.db = true
30
+ end
31
+
18
32
  opts.on("--skip-rails", "Skip Rails environment loading") do
19
- options[:skip_rails] = true
33
+ config.skip_rails = true
20
34
  end
21
35
 
22
36
  opts.on("-j", "--json", "Output results as JSON") do
23
- options[:json] = true
37
+ config.json = true
38
+ end
39
+
40
+ opts.on("--html", "Generate a visual HTML report (rails_benchmark_report.html)") do
41
+ config.html = true
24
42
  end
25
43
 
26
44
  opts.on("-h", "--help", "Prints this help") do
@@ -29,21 +47,26 @@ OptionParser.new do |opts|
29
47
  end
30
48
  end.parse!
31
49
 
32
- puts "RailsBenchmarkSuite v#{RailsBenchmarkSuite::VERSION}"
50
+ unless config.json
51
+ puts "RailsBenchmarkSuite v#{RailsBenchmarkSuite::VERSION}"
52
+ puts "Configuration: Threads=#{config.threads} | Profile=#{config.profile} | Local DB=#{config.db}"
53
+ end
33
54
 
34
55
  # Rails Detection
35
56
  rails_env_path = File.join(Dir.pwd, "config", "environment.rb")
36
57
 
37
- if !options[:skip_rails] && File.exist?(rails_env_path)
38
- puts "Rails environment detected at #{rails_env_path}. Loading..."
58
+ if !config.skip_rails && File.exist?(rails_env_path)
59
+ puts "Rails environment detected at #{rails_env_path}. Loading..." unless config.json
39
60
  require rails_env_path
40
- puts "Rails loaded successfully."
61
+ puts "Rails loaded successfully." unless config.json
41
62
  else
42
- if options[:skip_rails]
43
- puts "Skipping Rails loading (requested via --skip-rails)."
44
- else
45
- puts "No Rails environment detected (config/environment.rb not found)."
63
+ unless config.json
64
+ if config.skip_rails
65
+ puts "Skipping Rails loading (requested via --skip-rails)."
66
+ else
67
+ puts "No Rails environment detected (config/environment.rb not found)."
68
+ end
46
69
  end
47
70
  end
48
71
 
49
- RailsBenchmarkSuite.run(json: options[:json])
72
+ RailsBenchmarkSuite::Runner.new(config).run
Binary file
@@ -0,0 +1,7 @@
1
+ module RailsBenchmarkSuite
2
+ module Dummy
3
+ class BenchmarkJob < ActiveRecord::Base
4
+ self.table_name = "simulated_jobs" # Keep table name consistent or rename? Let's use simulated_jobs as it's descriptive
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ module RailsBenchmarkSuite
2
+ module Dummy
3
+ class BenchmarkPost < ActiveRecord::Base
4
+ self.table_name = "benchmark_posts"
5
+
6
+ belongs_to :user, class_name: "RailsBenchmarkSuite::Dummy::BenchmarkUser", foreign_key: "benchmark_user_id"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module RailsBenchmarkSuite
2
+ module Dummy
3
+ class BenchmarkUser < ActiveRecord::Base
4
+ self.table_name = "benchmark_users"
5
+
6
+ has_many :posts, class_name: "RailsBenchmarkSuite::Dummy::BenchmarkPost", foreign_key: "benchmark_user_id"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ <h1>Dashboard for <%= user.name %></h1>
2
+ <ul>
3
+ <% posts.each do |post| %>
4
+ <li>
5
+ <strong><%= post.title %></strong>
6
+ <p><%= post.body.truncate(50) %></p>
7
+ <small>Views: <%= number_with_delimiter(post.views) %></small>
8
+ </li>
9
+ <% end %>
10
+ </ul>
11
+ <footer>Generated at <%= Time.now.to_s %></footer>
@@ -0,0 +1,16 @@
1
+ # Dummy DB Config for isolated benchmarking
2
+ test:
3
+ adapter: sqlite3
4
+ database: ":memory:"
5
+ pool: 50
6
+ timeout: 5000
7
+
8
+ development:
9
+ adapter: sqlite3
10
+ database: "file:dummy_bench.sqlite3?mode=memory&cache=shared"
11
+ pool: 50
12
+ timeout: 30000
13
+ # High performance settings
14
+ variables:
15
+ journal_mode: WAL
16
+ synchronous: NORMAL
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "etc"
4
+
5
+ module RailsBenchmarkSuite
6
+ class Configuration
7
+ attr_accessor :threads, :profile, :db, :skip_rails, :json, :html
8
+
9
+ def initialize
10
+ @threads = Etc.nprocessors
11
+ @profile = false
12
+ @db = false
13
+ @skip_rails = false
14
+ @json = false
15
+ @html = false
16
+ end
17
+
18
+ def db_mode
19
+ @db ? "Local DB" : "SQLite (Memory)"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record"
4
+ require "yaml"
5
+
6
+ module RailsBenchmarkSuite
7
+ class DatabaseManager
8
+ SETUP_MUTEX = Mutex.new
9
+
10
+ def setup(use_local_db: false)
11
+ # Silence migrations
12
+ ActiveRecord::Migration.verbose = false
13
+
14
+ if use_local_db
15
+ setup_real_database
16
+ else
17
+ setup_dummy_database
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def setup_real_database
24
+ config_path = File.join(Dir.pwd, "config", "database.yml")
25
+ unless File.exist?(config_path)
26
+ raise "Database config not found at #{config_path} (required for --db option)"
27
+ end
28
+
29
+ db_config = YAML.load_file(config_path)
30
+ env = defined?(Rails) ? Rails.env : "development"
31
+
32
+ ActiveRecord::Base.establish_connection(db_config[env])
33
+ puts "Connected to local database (#{env})"
34
+ end
35
+
36
+ def setup_dummy_database
37
+ # Load internal dummy config
38
+ config_path = File.expand_path("../dummy/config/benchmark_database.yml", __dir__)
39
+ db_config = YAML.load_file(config_path)
40
+
41
+ # Use "development" profile which has the PRAGMA optimizations
42
+ ActiveRecord::Base.establish_connection(db_config["development"])
43
+
44
+ # Apply manual optimizations if needed (though config should handle it)
45
+ conn = ActiveRecord::Base.connection.raw_connection
46
+ conn.busy_timeout = 10000
47
+
48
+ # Setup Schema once safely
49
+ SETUP_MUTEX.synchronize do
50
+ unless ActiveRecord::Base.connection.table_exists?(:benchmark_users)
51
+ RailsBenchmarkSuite::Schema.load
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -5,3 +5,6 @@ require "sqlite3"
5
5
 
6
6
  # Silence ActiveRecord logs during benchmarks to avoid IO bottlenecks
7
7
  ActiveRecord::Base.logger = nil
8
+
9
+ # Silence migration output
10
+ ActiveRecord::Migration.verbose = false
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "rails_benchmark_suite/dummy/app/models/benchmark_user"
4
+ require "rails_benchmark_suite/dummy/app/models/benchmark_post"
5
+
3
6
  module RailsBenchmarkSuite
4
7
  module Models
5
- class User < ActiveRecord::Base
6
- has_many :posts, class_name: "RailsBenchmarkSuite::Models::Post", dependent: :destroy
7
- end
8
+ # Proxy or Legacy support if needed, but primary logic is now in Dummy namespace
8
9
  end
9
10
  end