Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
703e9bb
Initial benchmark version
alexeyr Sep 22, 2025
8fcc3b9
Add production scripts
alexeyr Oct 2, 2025
baea242
Initial benchmark workflow
alexeyr Oct 3, 2025
42061f7
Add server warm-up to benchmark
alexeyr Nov 5, 2025
efb4854
Make request timeout a parameter
alexeyr Nov 5, 2025
bc6a880
Update defaults for now
alexeyr Nov 5, 2025
a270da6
Fix knip error
alexeyr Nov 5, 2025
943cee8
Enable clustered mode in production
alexeyr Nov 5, 2025
11aefcf
Add MAX_CONNECTIONS
alexeyr Nov 5, 2025
1a57bf4
Fix max rate K6 scenario
alexeyr Nov 5, 2025
2645dc3
Reorder workflow parameters more logically
alexeyr Nov 5, 2025
d2f4254
Closer to recommended Fortio options
alexeyr Nov 5, 2025
84d76a5
Allow configuring RAILS_MAX/MIN_THREADS in the workflow
alexeyr Nov 5, 2025
3f0f3d4
Move showing benchmark params to bench.sh for simplicity
alexeyr Nov 5, 2025
11ed6c9
Convert the benchmark script to Ruby
alexeyr Nov 7, 2025
c0f7322
Fix k6 timeout
alexeyr Nov 7, 2025
6b64922
Replace DURATION_SEC with DURATION
alexeyr Nov 7, 2025
e86cb1e
Group all code for a tool into a single block
alexeyr Nov 7, 2025
8145e36
Remove duplication in adding summaries
alexeyr Nov 7, 2025
64b0d6b
Benchmark all routes
alexeyr Nov 8, 2025
e31d4a6
Fix Fortio failure on server_side_log_throw_raise
alexeyr Nov 8, 2025
a3866f3
Allow specifying routes
alexeyr Nov 8, 2025
a914dcd
Add pro benchmarks
alexeyr Nov 8, 2025
3f7224f
Update Claude instructions
alexeyr Nov 8, 2025
1ee85ef
FIXME temp commit
alexeyr Nov 11, 2025
a358195
Update prod-assets to include generate_packs
alexeyr Nov 11, 2025
3aa40f2
Disable js_compressor and css_compressor
alexeyr Nov 11, 2025
24ef5a3
Remove unused pg gem
alexeyr Nov 11, 2025
2943eaf
Handle empty inputs correctly
alexeyr Nov 11, 2025
2f658c5
Fix app version handling in the benchmark workflow
alexeyr Nov 11, 2025
a175f08
Fix starting/stopping servers
alexeyr Nov 11, 2025
b44f351
Simplify validate steps
alexeyr Nov 12, 2025
40029fa
Temp config to speed up
alexeyr Nov 12, 2025
88dc86e
Optimize tools installation
alexeyr Nov 12, 2025
1404c7b
Add logging to server check
alexeyr Nov 12, 2025
e22d3db
Make installs frozen
alexeyr Nov 12, 2025
b7f635b
Allow redirects in server_responding
alexeyr Nov 12, 2025
8f18ead
Try full Pro benchmark
alexeyr Nov 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
508 changes: 508 additions & 0 deletions .github/workflows/benchmark.yml

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ yalc.lock
/spec/dummy/.bsb.lock
/spec/dummy/**/*.res.js

# Performance test results
/bench_results

# Generated by ROR FS-based Registry
generated

Expand Down
2 changes: 2 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ Pre-commit hooks automatically run:
- All linters: `rake lint` (runs ESLint and RuboCop)
- ESLint only: `yarn run lint` or `rake lint:eslint`
- RuboCop only: `rake lint:rubocop`
- GitHub Action files (workflows, reusable actions, etc.): `actionlint`
- YAML files: `yamllint` (or validate the syntax with Ruby if it isn't installed). Do _not_ try to run RuboCop on `.yml` files.
- **Code Formatting**:
- Format code with Prettier: `rake autofix`
- Check formatting without fixing: `yarn start format.listDifferent`
Expand Down
3 changes: 3 additions & 0 deletions knip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ const config: KnipConfig = {
ignoreBinaries: [
// Has to be installed globally
'yalc',
'ruby',
// Used in package.json scripts (devDependency, so unlisted in production mode)
'nps',
// Pro package binaries used in Pro workflows
'playwright',
'e2e-test',
// Local binaries
'bin/.*',
],
ignore: ['react_on_rails_pro/**'],
ignoreDependencies: [
Expand Down
3 changes: 0 additions & 3 deletions react_on_rails_pro/Gemfile.development_dependencies
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,9 @@ gem "puma", "~> 6"
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem "jbuilder"

gem "pg"

# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
gem "turbolinks"
gem "sqlite3", "~> 1.4"
gem "uglifier"
gem "jquery-rails"
gem "sprockets"
gem "sass-rails"
Expand Down
5 changes: 0 additions & 5 deletions react_on_rails_pro/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,6 @@ GEM
parser (3.3.3.0)
ast (~> 2.4.1)
racc
pg (1.5.6)
pp (0.6.2)
prettyprint
prettyprint (0.2.0)
Expand Down Expand Up @@ -414,8 +413,6 @@ GEM
turbolinks-source (5.2.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
uglifier (4.2.0)
execjs (>= 0.3.0, < 3)
unicode-display_width (2.5.0)
uri (1.0.3)
useragent (0.16.11)
Expand Down Expand Up @@ -468,7 +465,6 @@ DEPENDENCIES
net-http
net-imap
net-smtp
pg
pry (>= 0.14.1)
pry-byebug!
pry-doc
Expand All @@ -493,7 +489,6 @@ DEPENDENCIES
sprockets
sqlite3 (~> 1.4)
turbolinks
uglifier
web-console
webdrivers (= 5.3.0)
webmock
Expand Down
5 changes: 0 additions & 5 deletions react_on_rails_pro/spec/dummy/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,6 @@ GEM
parser (3.3.3.0)
ast (~> 2.4.1)
racc
pg (1.5.6)
pp (0.6.2)
prettyprint
prettyprint (0.2.0)
Expand Down Expand Up @@ -450,8 +449,6 @@ GEM
turbolinks-source (5.2.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
uglifier (4.2.0)
execjs (>= 0.3.0, < 3)
unicode-display_width (2.5.0)
uri (1.0.3)
useragent (0.16.11)
Expand Down Expand Up @@ -515,7 +512,6 @@ DEPENDENCIES
net-http
net-imap
net-smtp
pg
prism-rails
pry (>= 0.14.1)
pry-byebug!
Expand All @@ -542,7 +538,6 @@ DEPENDENCIES
sprockets
sqlite3 (~> 1.4)
turbolinks
uglifier
web-console
webdrivers (= 5.3.0)
webmock
Expand Down
29 changes: 29 additions & 0 deletions react_on_rails_pro/spec/dummy/bin/prod
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env bash

# Run only after ./prod-assets

# Check if assets are precompiled
MANIFEST="public/webpack/production/manifest.json"

if [ ! -d "public/assets" ]; then
echo "ERROR: public/assets not found. Run ./bin/prod-assets first"
exit 1
fi

if [ ! -f "$MANIFEST" ]; then
echo "ERROR: $MANIFEST not found. Run ./bin/prod-assets first"
exit 1
fi

# Simple up-to-date check: warn if source files are newer than manifest.json
if find client config -type f \( -name "*.[jt]s" -o -name "*.[jt]sx" \) -newer "$MANIFEST" 2>/dev/null | grep -q .; then
echo "WARNING: client or config has changes newer than compiled assets"
echo "Consider running ./bin/prod-assets to rebuild"
fi

if [ -f "yarn.lock" ] && [ "yarn.lock" -nt "$MANIFEST" ]; then
echo "WARNING: yarn.lock is newer than compiled assets"
echo "Consider running ./bin/prod-assets to rebuild"
fi

NODE_ENV=production RAILS_ENV=production bundle exec rails server -p 3001
9 changes: 9 additions & 0 deletions react_on_rails_pro/spec/dummy/bin/prod-assets
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash

export NODE_ENV=production
export RAILS_ENV=production
if [ "$CI" = "true" ]; then
bundle exec bootsnap precompile --gemfile app/ lib/ config/
fi
bundle exec rails react_on_rails:generate_packs
bundle exec rails assets:precompile
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@
config.public_file_server.enabled = true

# Compress JavaScripts and CSS.
config.assets.js_compressor = Uglifier.new(harmony: true)
config.assets.css_compressor = :csso
# JS/CSS compression handled by Webpack/Shakapacker, not needed for Sprockets
# config.assets.js_compressor = Uglifier.new(harmony: true)
# config.assets.css_compressor = :csso

# Do not fallback to assets pipeline if a precompiled asset is missed.
config.assets.compile = false
Expand Down Expand Up @@ -69,7 +70,7 @@
config.active_support.deprecation = :notify

# Use default logging formatter so that PID and timestamp are not suppressed.
config.log_formatter = ::Logger::Formatter.new
config.log_formatter = Logger::Formatter.new

# Use a different logger for distributed setups.
# require 'syslog/logger'
Expand Down
3 changes: 3 additions & 0 deletions spec/dummy/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,8 @@ GEM
nokogiri (1.18.10)
mini_portile2 (~> 2.8.2)
racc (~> 1.4)
nokogiri (1.18.10-x86_64-linux-gnu)
racc (~> 1.4)
ostruct (0.6.3)
package_json (0.1.0)
parallel (1.24.0)
Expand Down Expand Up @@ -408,6 +410,7 @@ GEM

PLATFORMS
ruby
x86_64-linux

DEPENDENCIES
amazing_print
Expand Down
29 changes: 29 additions & 0 deletions spec/dummy/bin/prod
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/usr/bin/env bash

# Run only after ./prod-assets

# Check if assets are precompiled
MANIFEST="public/webpack/production/manifest.json"

if [ ! -d "public/assets" ]; then
echo "ERROR: public/assets not found. Run ./bin/prod-assets first"
exit 1
fi

if [ ! -f "$MANIFEST" ]; then
echo "ERROR: $MANIFEST not found. Run ./bin/prod-assets first"
exit 1
fi

# Simple up-to-date check: warn if source files are newer than manifest.json
if find client config -type f \( -name "*.[jt]s" -o -name "*.[jt]sx" \) -newer "$MANIFEST" 2>/dev/null | grep -q .; then
echo "WARNING: client or config has changes newer than compiled assets"
echo "Consider running ./bin/prod-assets to rebuild"
fi

if [ -f "yarn.lock" ] && [ "yarn.lock" -nt "$MANIFEST" ]; then
echo "WARNING: yarn.lock is newer than compiled assets"
echo "Consider running ./bin/prod-assets to rebuild"
fi

NODE_ENV=production RAILS_ENV=production bundle exec rails server -p 3001
9 changes: 9 additions & 0 deletions spec/dummy/bin/prod-assets
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/usr/bin/env bash

export NODE_ENV=production
export RAILS_ENV=production
if [ "$CI" = "true" ]; then
bundle exec bootsnap precompile --gemfile app/ lib/ config/
fi
yarn run build:rescript
bundle exec rails assets:precompile
41 changes: 25 additions & 16 deletions spec/dummy/config/puma.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,36 +10,45 @@
min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count }
threads min_threads_count, max_threads_count

rails_env = ENV.fetch("RAILS_ENV", "development")

# Specifies the `worker_timeout` threshold that Puma will use to wait before
# terminating a worker in development environments.
#
worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development"
worker_timeout 3600 if rails_env == "development"

# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
#
port ENV.fetch("PORT", 3000)

# Specifies the `environment` that Puma will run in.
#
environment ENV.fetch("RAILS_ENV", "development")
environment rails_env

# Specifies the `pidfile` that Puma will use.
pidfile ENV.fetch("PIDFILE", "tmp/pids/server.pid")

# Specifies the number of `workers` to boot in clustered mode.
# Workers are forked web server processes. If using threads and workers together
# the concurrency of the application would be max `threads` * `workers`.
# Workers do not work on JRuby or Windows (both of which do not support
# processes).
#
# workers ENV.fetch("WEB_CONCURRENCY") { 2 }

# Use the `preload_app!` method when specifying a `workers` number.
# This directive tells Puma to first boot the application and load code
# before forking the application. This takes advantage of Copy On Write
# process behavior so workers use less memory.
#
# preload_app!
if rails_env == "production"
# Specifies the number of `workers` to boot in clustered mode.
# Workers are forked web server processes. If using threads and workers together
# the concurrency of the application would be max `threads` * `workers`.
# Workers do not work on JRuby or Windows (both of which do not support
# processes).
#
workers ENV.fetch("WEB_CONCURRENCY", 2)

# Use the `preload_app!` method when specifying a `workers` number.
# This directive tells Puma to first boot the application and load code
# before forking the application. This takes advantage of Copy On Write
# process behavior so workers use less memory.
#
preload_app!

# Specifies the `worker_shutdown_timeout` threshold that Puma will use to wait before
# terminating a worker.
#
worker_shutdown_timeout 60
end

# Allow puma to be restarted by `bin/rails restart` command.
plugin :tmp_restart
Loading