Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
997e8c9
Initial benchmark version
alexeyr Sep 22, 2025
aefdd45
Add production scripts
alexeyr Oct 2, 2025
7833460
Initial benchmark workflow
alexeyr Oct 3, 2025
571f8b8
Add server warm-up to benchmark
alexeyr Nov 5, 2025
5c518e9
Make request timeout a parameter
alexeyr Nov 5, 2025
a4609d3
Update defaults for now
alexeyr Nov 5, 2025
cfe93e6
Fix knip error
alexeyr Nov 5, 2025
6e7c847
Enable clustered mode in production
alexeyr Nov 5, 2025
ff915e5
Add MAX_CONNECTIONS
alexeyr Nov 5, 2025
7b36b52
Fix max rate K6 scenario
alexeyr Nov 5, 2025
06c141d
Reorder workflow parameters more logically
alexeyr Nov 5, 2025
cc4f4db
Closer to recommended Fortio options
alexeyr Nov 5, 2025
745c73c
Allow configuring RAILS_MAX/MIN_THREADS in the workflow
alexeyr Nov 5, 2025
7efe9b6
Move showing benchmark params to bench.sh for simplicity
alexeyr Nov 5, 2025
97fa1cc
Convert the benchmark script to Ruby
alexeyr Nov 7, 2025
64a3b71
Fix k6 timeout
alexeyr Nov 7, 2025
de8a885
Replace DURATION_SEC with DURATION
alexeyr Nov 7, 2025
2379a63
Group all code for a tool into a single block
alexeyr Nov 7, 2025
2054cfd
Remove duplication in adding summaries
alexeyr Nov 7, 2025
103f6d5
Benchmark all routes
alexeyr Nov 8, 2025
dc96f80
Fix Fortio failure on server_side_log_throw_raise
alexeyr Nov 8, 2025
e14fc93
Allow specifying routes
alexeyr Nov 8, 2025
40c72ce
Add pro benchmarks
alexeyr Nov 8, 2025
a362d91
Update Claude instructions
alexeyr Nov 8, 2025
ab23c25
FIXME temp commit
alexeyr Nov 11, 2025
d38d314
Update prod-assets to include generate_packs
alexeyr Nov 11, 2025
54ec326
Disable js_compressor and css_compressor
alexeyr Nov 11, 2025
8aa38e2
Remove unused pg gem
alexeyr Nov 11, 2025
8414322
Handle empty inputs correctly
alexeyr Nov 11, 2025
34fd9fb
Fix app version handling in the benchmark workflow
alexeyr Nov 11, 2025
b655ba5
Fix starting/stopping servers
alexeyr Nov 11, 2025
5618a25
Simplify validate steps
alexeyr Nov 12, 2025
8aee006
Temp config to speed up
alexeyr Nov 12, 2025
bcd7029
Optimize tools installation
alexeyr Nov 12, 2025
a0e790f
Add logging to server check
alexeyr Nov 12, 2025
5eac989
Make installs frozen
alexeyr Nov 12, 2025
54241f6
Allow redirects in server_responding
alexeyr Nov 12, 2025
422fa43
Try full Pro benchmark
alexeyr Nov 12, 2025
db480bf
Update Core dummy path
alexeyr Dec 1, 2025
530d99b
Temporary root RuboCop config
alexeyr Dec 1, 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
519 changes: 519 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 @@ -76,6 +76,9 @@ react_on_rails/spec/dummy/**/*.res.js
react_on_rails_pro/spec/dummy/.bsb.lock
react_on_rails_pro/spec/dummy/**/*.res.js

# Performance test results
/bench_results

# Generated by ROR FS-based Registry
generated

Expand Down
9 changes: 9 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Root config reuses the one from react_on_rails for now,
# later it should be the other way around
inherit_from: react_on_rails/.rubocop.yml

AllCops:
Exclude:
- 'gen-examples/**/*'
- 'react_on_rails/**/*'
- 'react_on_rails_pro/**/*'
2 changes: 2 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ Pre-commit hooks automatically run:
- All linters: `rake lint` (runs ESLint and RuboCop)
- ESLint only: `pnpm 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: `pnpm run format.listDifferent`
Expand Down
2 changes: 2 additions & 0 deletions knip.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ const config: KnipConfig = {
// Pro package binaries used in Pro workflows
'playwright',
'e2e-test',
// Local binaries
'bin/.*',
],
ignore: ['react_on_rails_pro/**', 'react_on_rails/vendor/**'],
ignoreDependencies: [
Expand Down
3 changes: 3 additions & 0 deletions react_on_rails/spec/dummy/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,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 @@ -423,6 +425,7 @@ GEM

PLATFORMS
ruby
x86_64-linux

DEPENDENCIES
amazing_print
Expand Down
29 changes: 29 additions & 0 deletions react_on_rails/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/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 react_on_rails/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
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 @@ -250,7 +250,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 @@ -434,8 +433,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 @@ -488,7 +485,6 @@ DEPENDENCIES
net-http
net-imap
net-smtp
pg
pry (>= 0.14.1)
pry-byebug!
pry-doc
Expand All @@ -514,7 +510,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 @@ -275,7 +275,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 @@ -470,8 +469,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 @@ -535,7 +532,6 @@ DEPENDENCIES
net-http
net-imap
net-smtp
pg
prism-rails
pry (>= 0.14.1)
pry-byebug!
Expand Down Expand Up @@ -563,7 +559,6 @@ DEPENDENCIES
sprockets
sqlite3 (~> 1.4)
turbolinks
uglifier
web-console
webdrivers (= 5.3.0)
webmock
Expand Down
6 changes: 6 additions & 0 deletions react_on_rails_pro/spec/dummy/Procfile.prod
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Procfile for production mode (precompiled assets)

rails: RAILS_ENV=production NODE_ENV=production bin/rails s -p 3001

# Start Node server for server rendering.
node-renderer: NODE_ENV=production RENDERER_LOG_LEVEL=error RENDERER_PORT=3800 node client/node-renderer.js
40 changes: 40 additions & 0 deletions react_on_rails_pro/spec/dummy/bin/prod
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/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

export NODE_ENV=production
export RAILS_ENV=production

if command -v overmind &> /dev/null; then
overmind start -f Procfile.prod
elif command -v foreman &> /dev/null; then
foreman start -f Procfile.prod
else
echo "Installing foreman..."
gem install foreman
foreman start -f Procfile.prod
fi
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 @@ -3,6 +3,9 @@
Rails.application.configure do
# Settings specified here will take precedence over those in config/application.rb.

# Use a hardcoded secret for this test/dummy app (not for real production use)
config.secret_key_base = ENV.fetch("SECRET_KEY_BASE", "dummy-secret-key-base-for-testing-only")

# Code is not reloaded between requests.
config.cache_classes = true

Expand All @@ -19,8 +22,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
Loading
Loading