Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SSR benchmark script #1555

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 10 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,16 @@ Run `docker-compose build ci` to build the CI container. Run `docker-compose run

Run `docker-compose build tests` to build the tests container. Run `docker-compose run tests` to start all RSpec tests.

### Server-side-rendering performance benchmarking

See a simple example of benchmarking different ExecJS runtimes (NodeJS, [MiniRacer](https://github.com/rubyjs/mini_racer), [Alaska](https://github.com/mavenlink/alaska)) in `spec/dummy/bin/benchmark`.

After setting up the dummy app (`spec/dummy`), run:
```bash
cd spec/dummy
bin/benchmark
```

# Advice for Project Maintainers and Contributors

What do project maintainers do? What sort of work is involved? [sstephenson](https://github.com/sstephenson) wrote in the [turbolinks](https://github.com/turbolinks/turbolinks) repo:
Expand Down
8 changes: 6 additions & 2 deletions Gemfile.development_dependencies
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

gem "shakapacker", "6.5.1"
gem "bootsnap", require: false
gem "rails", "~> 7.0"
gem "rails", "~> 7.0", ">= 7.0.1"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for compatibility with Ruby 3.2.1

gem "sqlite3"
gem "sass-rails", "~> 6.0"
gem "uglifier"
Expand All @@ -24,7 +24,7 @@ gem "amazing_print"

group :development, :test do
gem "listen"
gem "pry"
gem "pry", ">= 0.14.2"
gem "pry-byebug"
gem "pry-doc"
gem "pry-rails"
Expand All @@ -34,6 +34,10 @@ group :development, :test do
gem "rubocop-rspec", require: false
gem "scss_lint", require: false
gem "spring", "~> 4.0"

# Example ExecJS runtimes
gem "mini_racer", require: false
gem "alaska", require: false
end

group :test do
Expand Down
157 changes: 91 additions & 66 deletions spec/dummy/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -11,67 +11,75 @@ PATH
GEM
remote: https://rubygems.org/
specs:
actioncable (7.0.0)
actionpack (= 7.0.0)
activesupport (= 7.0.0)
actioncable (7.0.6)
actionpack (= 7.0.6)
activesupport (= 7.0.6)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailbox (7.0.0)
actionpack (= 7.0.0)
activejob (= 7.0.0)
activerecord (= 7.0.0)
activestorage (= 7.0.0)
activesupport (= 7.0.0)
actionmailbox (7.0.6)
actionpack (= 7.0.6)
activejob (= 7.0.6)
activerecord (= 7.0.6)
activestorage (= 7.0.6)
activesupport (= 7.0.6)
mail (>= 2.7.1)
actionmailer (7.0.0)
actionpack (= 7.0.0)
actionview (= 7.0.0)
activejob (= 7.0.0)
activesupport (= 7.0.0)
net-imap
net-pop
net-smtp
actionmailer (7.0.6)
actionpack (= 7.0.6)
actionview (= 7.0.6)
activejob (= 7.0.6)
activesupport (= 7.0.6)
mail (~> 2.5, >= 2.5.4)
net-imap
net-pop
net-smtp
rails-dom-testing (~> 2.0)
actionpack (7.0.0)
actionview (= 7.0.0)
activesupport (= 7.0.0)
rack (~> 2.0, >= 2.2.0)
actionpack (7.0.6)
actionview (= 7.0.6)
activesupport (= 7.0.6)
rack (~> 2.0, >= 2.2.4)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actiontext (7.0.0)
actionpack (= 7.0.0)
activerecord (= 7.0.0)
activestorage (= 7.0.0)
activesupport (= 7.0.0)
actiontext (7.0.6)
actionpack (= 7.0.6)
activerecord (= 7.0.6)
activestorage (= 7.0.6)
activesupport (= 7.0.6)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
actionview (7.0.0)
activesupport (= 7.0.0)
actionview (7.0.6)
activesupport (= 7.0.6)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
activejob (7.0.0)
activesupport (= 7.0.0)
activejob (7.0.6)
activesupport (= 7.0.6)
globalid (>= 0.3.6)
activemodel (7.0.0)
activesupport (= 7.0.0)
activerecord (7.0.0)
activemodel (= 7.0.0)
activesupport (= 7.0.0)
activestorage (7.0.0)
actionpack (= 7.0.0)
activejob (= 7.0.0)
activerecord (= 7.0.0)
activesupport (= 7.0.0)
activemodel (7.0.6)
activesupport (= 7.0.6)
activerecord (7.0.6)
activemodel (= 7.0.6)
activesupport (= 7.0.6)
activestorage (7.0.6)
actionpack (= 7.0.6)
activejob (= 7.0.6)
activerecord (= 7.0.6)
activesupport (= 7.0.6)
marcel (~> 1.0)
mini_mime (>= 1.1.0)
activesupport (7.0.0)
activesupport (7.0.6)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
alaska (1.2.2)
execjs (~> 2.7)
amazing_print (1.2.2)
ast (2.4.2)
bootsnap (1.7.2)
Expand Down Expand Up @@ -99,6 +107,7 @@ GEM
thor (>= 0.19.4, < 2.0)
tins (~> 1.6)
crass (1.0.6)
date (3.3.3)
diff-lcs (1.4.4)
docile (1.3.5)
equivalent-xml (0.6.0)
Expand All @@ -109,7 +118,7 @@ GEM
generator_spec (0.9.4)
activesupport (>= 3.0.0)
railties (>= 3.0.0)
globalid (1.0.0)
globalid (1.1.0)
activesupport (>= 5.0)
i18n (1.8.11)
concurrent-ruby (~> 1.0)
Expand All @@ -123,33 +132,46 @@ GEM
json (2.5.1)
launchy (2.5.0)
addressable (~> 2.7)
libv8-node (18.16.0.0-arm64-darwin)
listen (3.4.1)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
loofah (2.13.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.7.1)
mail (2.8.1)
mini_mime (>= 0.1.1)
net-imap
net-pop
net-smtp
marcel (1.0.2)
method_source (1.0.0)
mini_mime (1.1.2)
mini_portile2 (2.8.1)
mini_racer (0.8.0)
libv8-node (~> 18.16.0.0)
minitest (5.15.0)
msgpack (1.4.2)
net-imap (0.3.6)
date
net-protocol
net-pop (0.1.2)
net-protocol
net-protocol (0.2.1)
timeout
net-smtp (0.3.3)
net-protocol
nio4r (2.5.8)
nokogiri (1.14.3)
mini_portile2 (~> 2.8.0)
nokogiri (1.14.3-arm64-darwin)
racc (~> 1.4)
parallel (1.20.1)
parser (3.0.1.1)
ast (~> 2.4.1)
pry (0.13.1)
pry (0.14.2)
coderay (~> 1.1)
method_source (~> 1.0)
pry-byebug (3.9.0)
pry-byebug (3.10.1)
byebug (~> 11.0)
pry (~> 0.13.0)
pry (>= 0.13, < 0.15)
pry-doc (1.1.0)
pry (~> 0.11)
yard (~> 0.9.11)
Expand All @@ -162,33 +184,33 @@ GEM
puma (5.2.2)
nio4r (~> 2.0)
racc (1.6.2)
rack (2.2.3)
rack (2.2.7)
rack-proxy (0.7.4)
rack
rack-test (1.1.0)
rack (>= 1.0, < 3)
rails (7.0.0)
actioncable (= 7.0.0)
actionmailbox (= 7.0.0)
actionmailer (= 7.0.0)
actionpack (= 7.0.0)
actiontext (= 7.0.0)
actionview (= 7.0.0)
activejob (= 7.0.0)
activemodel (= 7.0.0)
activerecord (= 7.0.0)
activestorage (= 7.0.0)
activesupport (= 7.0.0)
rails (7.0.6)
actioncable (= 7.0.6)
actionmailbox (= 7.0.6)
actionmailer (= 7.0.6)
actionpack (= 7.0.6)
actiontext (= 7.0.6)
actionview (= 7.0.6)
activejob (= 7.0.6)
activemodel (= 7.0.6)
activerecord (= 7.0.6)
activestorage (= 7.0.6)
activesupport (= 7.0.6)
bundler (>= 1.15.0)
railties (= 7.0.0)
railties (= 7.0.6)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
rails-html-sanitizer (1.4.2)
loofah (~> 2.3)
railties (7.0.0)
actionpack (= 7.0.0)
activesupport (= 7.0.0)
railties (7.0.6)
actionpack (= 7.0.6)
activesupport (= 7.0.6)
method_source
rake (>= 12.2)
thor (~> 1.0)
Expand Down Expand Up @@ -289,6 +311,7 @@ GEM
tins (~> 1.0)
thor (1.1.0)
tilt (2.0.10)
timeout (0.4.0)
tins (1.28.0)
sync
turbolinks (5.2.1)
Expand All @@ -313,9 +336,10 @@ GEM
zeitwerk (2.5.2)

PLATFORMS
ruby
arm64-darwin-22

DEPENDENCIES
alaska
amazing_print
bootsnap
bundler (= 2.4.9)
Expand All @@ -328,13 +352,14 @@ DEPENDENCIES
jquery-rails
launchy
listen
pry
mini_racer
pry (>= 0.14.2)
pry-byebug
pry-doc
pry-rails
pry-rescue
puma (~> 5.0)
rails (~> 7.0)
rails (~> 7.0, >= 7.0.1)
react_on_rails!
rspec-rails
rspec-retry
Expand Down
80 changes: 80 additions & 0 deletions spec/dummy/bin/benchmark
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/usr/bin/env bash

#
# A simple example of how to benchmark the dummy app.
#

set -euo pipefail

shutdown_server() {
if [ -f tmp/pids/server.pid ]; then
kill $(cat tmp/pids/server.pid)
rm -f tmp/pids/server.pid
fi
}

hit_backend() {
local pathname="$1"
curl "http://localhost:3000$pathname" \
--max-time 3 \
--silent \
--no-progress-meter \
--fail \
-w %{time_total} \
-o /dev/null
}

run_benchmarks() {
local runtime="$1"
local pathname="$2"

echo "Benchmarking with $runtime..."

# start dummy app server in background
MANUAL_EXECJS_RUNTIME="$runtime" \
RAILS_ENV=production \
bundle exec rails s -p 3000 &

sleep 3 # wait for server to start

echo "Warmup: $(hit_backend $pathname)"

durations=()
for i in {1..10}; do
dur=$(hit_backend $pathname)
durations+=("$dur")
echo "Request $i: ${dur}s"
done

echo "$runtime average: $(echo "${durations[*]}" | awk '{ total += $1 } END { print total/NR }')s"

shutdown_server
}

# If you modified `node_package` files, first follow the
# instructions in CONTRIBUTING.md to setup `yalc`.

# Build server-rendering assets:
# yarn build:rescript # if needed
rm -rf public/webpack
RAILS_ENV=production NODE_ENV=production bin/webpacker

# kill server on exit
trap shutdown_server EXIT

# kill any existing server
shutdown_server

# remove any existing logs
rm -f log/*.log

echo "Benchmarking server-side rendering..."

# run_benchmarks Node /render_js # FIXME: Node runtime is broken with this setup, it stalls infinitely.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weird.

Because if you uninstall MiniRacer, then ExecJS should use NodeJS by default & that seems to work correctly.

run_benchmarks MiniRacer /render_js
run_benchmarks Alaska /render_js

# FIXME: all others SSR endpoints are broken with this setup
# e.g. Hitting /server_side_hello_world gives error: "ActionView::Template::Error (Shakapacker can't find generated/HelloWorld.js in manifest.json"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here are the 2 FIXMEs ^ that I can't figure out. I'm unfamiliar with the generated/* files, can someone give me some advice here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's if you're using the auto bundles, so that you just use react_component and the bundle is included on the page automatically

https://github.com/shakacode/react_on_rails/blob/master/docs/guides/file-system-based-automated-bundle-generation.md

Copy link
Contributor Author

@wyattades wyattades Jul 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do I enable the generated routes on the dummy app?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wyattades you'l want to run bundle exec rake react_on_rails:generate_packs as part of the setup.


echo "Benchmarking complete!"
Loading
Loading