• Stars
    star
    212
  • Rank 186,122 (Top 4 %)
  • Language
    Ruby
  • License
    GNU General Publi...
  • Created about 8 years ago
  • Updated over 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A Rails-based benchmark for Ruby development

Rails Ruby Bench

Rails Ruby Bench (aka RRB) is a Discourse-based benchmark to measure the speed of the Ruby language. It can incidentally be used to measure the speed of a number of other things.

RRB is a "Real World" benchmark, in the sense of running a large Rails app in a concurrent configuration with a lot of complexity and variation in what it does. That makes it wonderful for measuring end-to-end effects of significant changes, and terrible for optimizing operations that don't take a lot of runtime.

This Discourse-based benchmark steals some code from Discourse (e.g. user_simulator.rb, seed_db_data.rb), so it's licensed GPLv2. It also uses Discourse.

I normally run this benchmark by building an AWS image using Packer and running it on a dedicated EC2 instance. For a variety of reasons, that gives very consistent benchmark results. It's also annoying for some use cases. If you can easily use AWS, I recommend it.

This benchmark was written and, for the first few years, maintained via AppFolio's sponsorship (https://engineering.appfolio.com). Thank you AppFolio!

Command-Line Options

Start.rb supports a number of options:

-r NUMBER      Set the random seed
-i NUMBER      Number of total iterations (default: 1500)
-n NUMBER      Number of load threads in the user simulator
-s NUMBER      Number of start/stop iterations, measuring time to first successful request
-w NUMBER      Number of warmup HTTP requests before timing
-p NUMBER      Port number for Puma server (default: 4567)
-o DIR         Directory for JSON output
-t NUMBER      Threads per Puma server
-c NUMBER      Number of cluster processes for Puma

Running the Benchmark Locally (Incomplete Version)

If you think your computer is basically set up for Discourse already, here's the short version of the configuration. Are you worried that you may need more software? Scroll down to the complete version of the setup below.

Make sure to run:

$ ./bin/setup

That script will install dependencies and Discourse, and then it will try to setup the database for Discourse.

Note that Discourse (at least version 1.8) does not support Postgresql 10, version 9 is needed.

Then, run the database seeding script:

$ cd ../.. # Back to root directory rather than work/discourse
$ RAILS_ENV=profile ruby seed_db_data.rb  # And wait awhile - it's slow

Now you can run the benchmark:

$ ./start.rb

Running the Benchmark Locally (Complete Version)

For the AWS build, RRB uses Packer to create an image configured for Discourse, 100% from scratch. That means the Packer directory includes all the necessary configuration scripts to make that happen.

For very good reasons, RRB's Packer build separates these scripts into a lot of small steps. So the configuration is annoying :-(

If you want to be 100% sure you have all the latest configuration steps, read packer/ami.json - that's the configuration file that Packer actually uses to build the image, so it's basically guaranteed to work. It runs a lot of other small scripts which are stored in the packer directory. If you have trouble with these instructions, you may want to refer to the runnable script.

RRB tries to keep an up-to-date local install script, but it does sometimes get out of date:

Switch to a 2.3.4 or 2.4.1 Ruby
$ ruby packer/setup.rb --local

You'll also need Discourse's dependencies - the benchmark uses Discourse, so you'll need to manage a local copy of Discourse. There's a script in the Discourse directory you can look at on OS X under work/discourse/script/osx_dev. Refer to this page for Linux.

Rerun the setup until it succeeds.

Then run start.rb to run the server and the benchmark.

Customizing the Benchmark

The benchmark uses the Ruby and Discourse versions found in setup.json. You can customize them there, then re-run setup.rb. You may need to clear the cloned versions in the work directory first.

Definitive Benchmark Numbers and AWS

The definitive version of the benchmark uses an AWS m4.2xlarge instance and an AMI. This has 8 vCPUs (4 virtual cores) as discussed in the design documentation, and doesn't have an excessive amount of memory or I/O priority. It's a realistic hosting choice at roughly $270/month if running continuously. Your benchmark should run in well under an hour and cost about $0.40 (40 cents) in USD.

To create your own AMI, see packer/README.md in this Git repo.

With your AMI (or using a public AMI), you can launch an instance as normal for AWS. Here's an example command line:

aws ec2 run-instances --image-id ami-f678218d --count 1 --instance-type m4.2xlarge --key-name MyKeyPair --placement Tenancy=dedicated

Replace "MyKeyPair" with the name of your own AWS keypair. You can, of course, replace the AMI ID with the current latest public AMI, or one you built.

The current publicly available AMIs are:

ami-554a4543 for Discourse v1.5 and Ruby 2.0.0 through 2.3.4

ami-f678218d for Discourse v1.8 and Ruby 2.3.4 and 2.4.1

Debugging with the AMI

Example command lines:

aws ec2 run-instances --count 1 --instance-type m4.2xlarge --key-name my-ssh-key-name --placement Tenancy=dedicated --image-id ami-f678218d
ssh -i ~/.ssh/my-ssh-key-name.pem [email protected]
cd rails_ruby_bench
./in_each_ruby.rb "for i in {1..20}; do ./start.rb -i 3000 -w 100 -s 0; done"

You'll need to find the public DNS name of the VM you created somehow. I normally use the EC2 dashboard. Similarly, you should use an SSH key name that exists in your AWS account. The parameters above are for an m4.2xlarge dedicated instance. That's a bit expensive, but will also give you reproducible results that you can compare directly with mine. If you use a much smaller instance, you'll want to reduce the number of load-testing threads and Puma processes and threads.

I normally copy the JSON files back to my own machine, something like:

scp -i /.ssh/my-ssh-key-name.pem [email protected]:/rails_ruby_bench/*.json ./my_local_directory

Debugging and AWS

By default, the Rails benchmark is git-cloned under ~ubuntu/rails_ruby_bench, and Discourse is cloned under the work subdirectory of that repository. The built Rubies are mounted using rvm for the benchmark. You can see them with "rvm list". If you want to change anything when starting your own instance, those are great places to begin.

By default, the image won't update or rebuild Ruby or Discourse, nor update the Rails Ruby benchmark on boot. It will use the versions of all of those things that were current when the AMI was built. But you can modify your own image later however you like.

If you'd like to change the behavior of the AWS image, you can use AWS user data to run a script on boot. See "http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html".

You can also just log in and make whatever changes you want, of course.

Decisions and Intent

  • Configurable Ruby, Rails and Discourse versions. This makes it easy to test a particular optimization or fix to any of Ruby, Rails or Discourse. To test other fixes to most software, the gem version in Rails can be updated at a different URL. This doesn't make it as easy to test fixes to system libraries or programs (e.g. libxml, postgres) which are less likely to be patched just because of Ruby performance.

  • Use Discourse code because it's a real Rails application, used in production, with a reasonably stable REST API. This tests many code paths in realistic proportions.

  • Use random seed for client because it provides a reasonable balance between unpredictability and stability. Note that no multithreaded or multiprocess benchmark using a host (real or virtual) is going to be fully reproducible or stable. But the random seed for client requests provides a baseline of reproducibility, within the limits of a benchmark that isn't extremely artificial.

  • Test with multiple requests at once because better Ruby concurrency is an explicit goal of Ruby 3x3. The first question most people ask of any Ruby optimization is "how much will it improve my Rails performance?" Concurrency is key to answering this question.

  • Use Puma because we want multithreaded operation. Multithreaded means Puma or Thin or commercial Passenger. Puma is more commonly used as a high-performance multithreaded Ruby application server at this point.

  • Use AWS because it's common, it's an industry standard and it's easy to test. Also, nearly all other cloud offerings are measured against AWS. AWS numbers will be treated as meaningful on their face.

  • Use postgres on same machine: on same machine to avoid AWS time in benchmarking, require Postgres because Discourse does and can't be easily changed. (https://meta.discourse.org/t/why-not-support-mysql/2568/2)

  • Use Sidekiq on same machine: on same machine to avoid AWS time in benchmarking, use Sidekiq because it's fast, simple, in Ruby and not trivial to change.

  • Don't use Discourse's existing benchmark script because it simply runs a (very) small set of URLs, and only tests one URL at once.

More Repositories

1

rulers

The Rulers framework from the Rebuilding Rails ebook - caution, will occasionally require a "git pull -f" due to rebase
Ruby
71
star
2

madscience

Obsolete: deploy your Rails app with a full dedicated server in an hour! The source for Ruby Mad Science and Rails Deploy In An Hour (Note: link is now to a different project!)
Ruby
67
star
3

env_mem

A simple memory tool to save memory configuration from a mature process to fast-start a newer instance of that process.
Ruby
48
star
4

rsb

Rails Simpler Bench - a simple Rails app, with a variety of requests and Ruby versions that it can be tested with
Ruby
42
star
5

best_quotes

This is the example best_quotes application from Rebuilding Rails' ebook. Caution, will occasionally require "git pull -f" due to rebase.
Ruby
22
star
6

madscience_gem

Source to the madscience Ruby gem. Part of RubyMadScience and Rails-Deploy-In-An-Hour.com
Ruby
19
star
7

navier

Playing with a Navier-Stokes fluid dynamics simulator based on Jos Stam's
JavaScript
11
star
8

orm

Demo ORM for GoGaRuCo
Ruby
10
star
9

r00lz

A teaching Rack framework for Rebuilding Rails' video series. Caution, will occasionally require a "git pull -f" due to modifications.
Ruby
10
star
10

fiber_basic_benchmarks

Simple server-based benchmarks for Fibers, Threads and Processes in Ruby
Ruby
9
star
11

RailsGame

Outdated: Rails plugin to create Rails-based server-push games.
Ruby
9
star
12

self_conscious_dgd

An Incomplete Programming Book about DGD
HTML
7
star
13

RailsMUD

An online HTML-and-text game based on Rails and Juggernaut. Proof-of-concept quality.
Ruby
6
star
14

rubymadscience

RubyMadScience.com experimental courseware
CSS
5
star
15

rebuilding_http

Code for the book 'Rebuilding HTTP'
Ruby
5
star
16

cheaptoad

A simple Hoptoad server plugin
Ruby
5
star
17

angelbox

Vagrant and Chef configuration for my deployed web box
Ruby
4
star
18

webconf

god and nginx config files for my web server
Shell
3
star
19

refactor_it_tutorial

Code for a Rails3 tutorial
Ruby
3
star
20

markov

A simple utility for generating random strings from Markov chains
Ruby
3
star
21

blog

Code for blog.angelbob.com. Finished and usable, if simple.
Ruby
3
star
22

Astrino

A RailsGame based on the ErfWorld web comic. A demo of RailsGame.
Ruby
3
star
23

www_static

Static WWW content for angelbob.com and related sites
HTML
2
star
24

bobfolio

This is an example programmer's portfolio - clone it and modify to make your own! Gratuitous plug:
JavaScript
2
star
25

ractor_basic_benchmarks

Simple benchmarking of Ruby 3 Ractors for a blog post
Ruby
2
star
26

easypartials

Run partials with even less syntactic overhead in your views
Ruby
2
star
27

statuesque

Describes objects in human-like terms
Ruby
2
star
28

noahgibbs.github.com

User page for me on GitHub
2
star
29

js_portfolio_example

Example JavaScript portfolio code
HTML
2
star
30

capybara-webview

A Webview driver for Capybara-Minitest, plus structure to use it with Webview process constraints
Ruby
2
star
31

wantmyjob.com

Peer-to-peer job search app for techies
Ruby
1
star
32

angelbob-rails-templates

Some rails templates I use
Ruby
1
star
33

frozen-hail

Demo project with Storm
Java
1
star
34

maslow

An AI project for a simple Maslow's-Hierarchy-based action evaluator for simulated critters
Ruby
1
star
35

jugworld

Juggernaut test server
Ruby
1
star
36

shannas_pizza

Outdated SDL-based circuit simulator game. Linux and Windows.
C
1
star
37

testing_rebuilding_http

Test repo that clones rebuilding_http and runs automated tests on it
Ruby
1
star
38

quotes

A test app for the r00lz teaching Rack framework from Rebuilding Rails' video series. May occasionally require "pull -f" due to modifications.
Ruby
1
star
39

roughshod

Code metrics tool to find code that changes too frequently from your Git history
Ruby
1
star
40

railsframe

A Rails app framework for easy virtualization and deployment
Ruby
1
star
41

faerie_media

Various notes, pictures and writing I've created or found, strong emphasis on CC0/PD content
1
star
42

refactor_it

A simple site that allows you to submit chunks of code and refactorings for it
Ruby
1
star
43

pg-rails-devise-pundit

Simple test app for Postgres
Ruby
1
star
44

codefolio_octopress

An Octopress generator for static Codefol.io content
HTML
1
star
45

programmer_portfolio

A quick programmer portfolio, suitable for upload to Heroku. Modify index.html with your own stuff.
CSS
1
star
46

markobj

1
star
47

rrb_datavis

Raw data and visualization scripts for Rails Ruby Bench, mostly related to my blog posts and talks.
HTML
1
star
48

mysql_bloat_test

A quick-and-dirty port of Sam Saffron's PostgreSQL bloat test to MySQL / mysql2
Ruby
1
star
49

cheaptoad-catcher

A very simple error server for Hoptoad/Cheaptoad
Ruby
1
star
50

codefolio_middleman

Middleman source for Codefol.io
HTML
1
star
51

diffeq

Differential Equations library written in Ruby
Ruby
1
star
52

snowfront

An HTML and CSS markdown-based game state front end, based on Twine's 'Snowman' story format.
JavaScript
1
star
53

shards_of_faerie

An attempt to put together a set of simple games on top of ActionCable
Ruby
1
star
54

GoblinMarket

A test repo for playing with the Godot Engine
1
star