Skip to content
Merged
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
22 changes: 14 additions & 8 deletions frameworks/Ruby/padrino/Gemfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
source 'https://rubygems.org'

gem 'mysql2', '~> 0.4'
gem "unicorn", '~> 6.1'
gem 'puma', '~> 6.4'
gem 'json', '~> 2.0'
gem 'mysql2', '> 0.5'
gem 'json'
gem 'activerecord', '>= 7.1', :require => 'active_record'

gem 'slim', '2.0.3'
gem 'dm-mysql-adapter', '1.2.0'
gem 'dm-core', '1.2.1'
gem 'padrino', '0.15.3'
gem 'rack', '~> 2.2'
gem 'padrino', git: 'https://github.com/padrino/padrino-framework.git'
gem 'rack'

group :puma, optional: true do
gem 'puma', '~> 6.4', require: false
end

group :unicorn, optional: true do
gem 'unicorn', '~> 6.1', platforms: [:ruby, :mswin], require: false
end
23 changes: 14 additions & 9 deletions frameworks/Ruby/padrino/app/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,16 @@ class App < Padrino::Application
#
# You can customize caching store engines:
#
# set :cache, Padrino::Cache::Store::Memcache.new(::Memcached.new('127.0.0.1:11211', :exception_retry_limit => 1))
# set :cache, Padrino::Cache::Store::Memcache.new(::Dalli::Client.new('127.0.0.1:11211', :exception_retry_limit => 1))
# set :cache, Padrino::Cache::Store::Redis.new(::Redis.new(:host => '127.0.0.1', :port => 6379, :db => 0))
# set :cache, Padrino::Cache::Store::Memory.new(50)
# set :cache, Padrino::Cache::Store::File.new(Padrino.root('tmp', app_name.to_s, 'cache')) # default choice
# set :cache, Padrino::Cache.new(:LRUHash) # Keeps cached values in memory
# set :cache, Padrino::Cache.new(:Memcached) # Uses default server at localhost
# set :cache, Padrino::Cache.new(:Memcached, :server => '127.0.0.1:11211', :exception_retry_limit => 1)
# set :cache, Padrino::Cache.new(:Memcached, :backend => memcached_or_dalli_instance)
# set :cache, Padrino::Cache.new(:Redis) # Uses default server at localhost
# set :cache, Padrino::Cache.new(:Redis, :host => '127.0.0.1', :port => 6379, :db => 0)
# set :cache, Padrino::Cache.new(:Redis, :backend => redis_instance)
# set :cache, Padrino::Cache.new(:Mongo) # Uses default server at localhost
# set :cache, Padrino::Cache.new(:Mongo, :backend => mongo_client_instance)
# set :cache, Padrino::Cache.new(:File, :dir => Padrino.root('tmp', app_name.to_s, 'cache')) # default choice
#

##
Expand All @@ -32,8 +37,8 @@ class App < Padrino::Application
# set :reload, false # Reload application files (default in development)
# set :default_builder, 'foo' # Set a custom form builder (default 'StandardFormBuilder')
# set :locale_path, 'bar' # Set path for I18n translations (default your_apps_root_path/locale)
# disable :sessions # Disabled sessions by default (enable if needed)
# disable :flash # Disables sinatra-flash (enabled by default if Sinatra::Flash is defined)
disable :sessions # Disabled sessions by default (enable if needed)
disable :flash # Disables sinatra-flash (enabled by default if Sinatra::Flash is defined)
# layout :my_layout # Layout can be in views/layouts/foo.ext or views/foo.ext (default :application)
#

Expand All @@ -53,8 +58,8 @@ class App < Padrino::Application
# render 'errors/404'
# end
#
# error 505 do
# render 'errors/505'
# error 500 do
# render 'errors/500'
# end
#
end
Expand Down
71 changes: 37 additions & 34 deletions frameworks/Ruby/padrino/app/controllers.rb
Original file line number Diff line number Diff line change
@@ -1,62 +1,65 @@
MAX_PK = 10_000
QUERIES_MIN = 1
QUERIES_MAX = 500
QUERY_RANGE = (1..10_000).freeze
ALL_IDS = QUERY_RANGE.to_a

HelloWorld::App.controllers do

after do
response['Server'] = 'padrino'
end

after do
response['Date'] = Time.now.httpdate
end if defined?(Puma)

get '/json', :provides => [:json] do
response.headers['Server'] = 'padrino'
response.headers['Date'] = Time.now.httpdate
{message: "Hello, World!"}.to_json
end

get '/db', :provides => [:json] do
response.headers['Server'] = 'padrino'
response.headers['Date'] = Time.now.httpdate
id = Random.rand(MAX_PK) + 1
World.get(id).attributes.to_json
world = ActiveRecord::Base.with_connection do
World.find(rand1).attributes
end
world.to_json
end

get '/queries', :provides => [:json] do
response.headers['Server'] = 'padrino'
response.headers['Date'] = Time.now.httpdate
queries = params['queries'].to_i.clamp(QUERIES_MIN, QUERIES_MAX)

results = (1..queries).map do
World.get(Random.rand(MAX_PK) + 1).attributes
end.to_json
worlds = ActiveRecord::Base.with_connection do
ALL_IDS.sample(bounded_queries).map do |id|
World.find(id).attributes
end
end
worlds.to_json
end

get '/fortunes' do
response.headers['Server'] = 'padrino'
response.headers['Date'] = Time.now.httpdate
@fortunes = Fortune.all
@fortunes << Fortune.new(:id => 0, :message => "Additional fortune added at request time.")
@fortunes = @fortunes.sort_by { |x| x.message }
@fortunes = Fortune.all.to_a
@fortunes << Fortune.new(
id: 0,
message: "Additional fortune added at request time."
)
@fortunes = @fortunes.sort_by(&:message)

render 'fortunes', layout: "layout"
end

get '/updates', :provides => [:json] do
response.headers['Server'] = 'padrino'
response.headers['Date'] = Time.now.httpdate
queries = params['queries'].to_i.clamp(QUERIES_MIN, QUERIES_MAX)

worlds = (1..queries).map do
# get a random row from the database, which we know has 10000
# rows with ids 1 - 10000
world = World.get(Random.rand(MAX_PK) + 1)
world.update(randomNumber: Random.rand(MAX_PK) + 1)
world.attributes
worlds = []
ActiveRecord::Base.with_connection do
worlds = ALL_IDS.sample(bounded_queries).map do |id|
world = World.find(id)
new_value = rand1
new_value = rand1 while new_value == world.randomNumber
world.randomNumber = new_value
world
end
World.upsert_all(worlds)
end

worlds.to_json
end

get '/plaintext' do
response.headers['Server'] = 'padrino'
response.headers['Date'] = Time.now.httpdate
content_type 'text/plain'
"Hello, World!"
end

end
15 changes: 12 additions & 3 deletions frameworks/Ruby/padrino/app/helpers.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
# Helper methods defined here can be accessed in any controller or view in the application

MAX_PK = 10_000
QUERIES_MIN = 1
QUERIES_MAX = 500

HelloWorld::App.helpers do
# def simple_helper_method
# ...
# end
def rand1
rand(MAX_PK) + 1
end

def bounded_queries
queries = params[:queries].to_i
queries.clamp(QUERIES_MIN, QUERIES_MAX)
end
end
6 changes: 3 additions & 3 deletions frameworks/Ruby/padrino/benchmark_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@
},
"unicorn": {
"json_url": "/json",
"db_url": "/db",
"query_url": "/queries?queries=",
"db_url": "/db",
"query_url": "/queries?queries=",
"fortune_url": "/fortunes",
"update_url": "/updates?queries=",
"update_url": "/updates?queries=",
"plaintext_url": "/plaintext",
"port": 8080,
"approach": "Realistic",
Expand Down
4 changes: 2 additions & 2 deletions frameworks/Ruby/padrino/config/apps.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
Padrino.configure_apps do
# enable :sessions
set :session_secret, 'b941cbcb2d647360c0d1fb3c54a7039ed4f71cc0b7785d2aac689cc37d7757b7'
set :protection, true
set :protect_from_csrf, true
set :protection, false
set :protect_from_csrf, false
end

# Mounts the core application for this project
Expand Down
1 change: 0 additions & 1 deletion frameworks/Ruby/padrino/config/boot.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
# Add your after (RE)load hooks here
#
Padrino.after_load do
DataMapper.finalize
end

Padrino.load!
45 changes: 30 additions & 15 deletions frameworks/Ruby/padrino/config/database.rb
Original file line number Diff line number Diff line change
@@ -1,17 +1,32 @@
##
# A MySQL connection:
# DataMapper.setup(:default, 'mysql://user:password@localhost/the_database_name')
#
# # A Postgres connection:
# DataMapper.setup(:default, 'postgres://user:password@localhost/the_database_name')
#
# # A Sqlite3 connection
# DataMapper.setup(:default, "sqlite3://" + Padrino.root('db', "development.db"))
#
Bundler.require('mysql')
opts = {
adapter: 'mysql2',
username: 'benchmarkdbuser',
password: 'benchmarkdbpass',
host: 'tfb-database',
database: 'hello_world'
}

DataMapper.logger = logger
DataMapper::Property::String.length(255)

case Padrino.env
when :production then DataMapper.setup(:default, "mysql://benchmarkdbuser:benchmarkdbpass@tfb-database/hello_world")
# Determine threading/thread pool size and timeout
if defined?(Puma) && (threads = Puma.cli_config.options.fetch(:max_threads)) > 1
opts[:pool] = (2 * Math.log(threads)).floor
opts[:checkout_timeout] = 10
else
# TODO: ActiveRecord doesn't have a single-threaded mode?
opts[:pool] = 1
opts[:checkout_timeout] = 0
end


# Setup our logger
ActiveRecord::Base.logger = logger

# Use ISO 8601 format for JSON serialized times and dates.
ActiveSupport.use_standard_json_time_format = true

# Don't escape HTML entities in JSON, leave that for the #json_escape helper
# if you're including raw JSON in an HTML page.
ActiveSupport.escape_html_entities_in_json = false

# Now we can establish connection with our db.
ActiveRecord::Base.establish_connection(opts)
10 changes: 2 additions & 8 deletions frameworks/Ruby/padrino/models/fortune.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
class Fortune
include DataMapper::Resource

storage_names[:default] = 'Fortune'

# property <name>, <type>
property :id, Serial
property :message, String
class Fortune < ActiveRecord::Base
self.table_name = name
end
19 changes: 13 additions & 6 deletions frameworks/Ruby/padrino/models/world.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
class World
include DataMapper::Resource
class World < ActiveRecord::Base
self.table_name = name

storage_names[:default] = 'World'
alias_attribute(:randomNumber, :randomnumber) \
if connection.adapter_name.downcase.start_with?('postgres')

# property <name>, <type>
property :id, Serial
property :randomNumber, Integer, field: 'randomNumber'
if connection.adapter_name.downcase.start_with?('mysql')
def self.upsert_all(attributes, on_duplicate: :update, update_only: nil, returning: nil, unique_by: nil, record_timestamps: nil)
# On MySQL Batch updates verification isn't supported yet by TechEmpower.
# https://github.com/TechEmpower/FrameworkBenchmarks/issues/5983
attributes.each do |attrs|
where(id: attrs[:id]).update_all(randomNumber: attrs[:randomNumber])
end
end
end
end
5 changes: 4 additions & 1 deletion frameworks/Ruby/padrino/padrino-unicorn.dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM ruby:3.0
FROM ruby:3.4

WORKDIR /padrino
COPY app app
Expand All @@ -9,11 +9,14 @@ COPY config.ru config.ru
COPY Gemfile Gemfile
COPY Rakefile Rakefile

RUN bundle config set with 'unicorn'
RUN bundle install --jobs=4 --gemfile=/padrino/Gemfile

RUN apt-get update -yqq && apt-get install -yqq nginx

EXPOSE 8080

ENV RUBY_YJIT_ENABLE=1

CMD nginx -c /padrino/config/nginx.conf && \
bundle exec unicorn -E production -c config/unicorn.rb
7 changes: 5 additions & 2 deletions frameworks/Ruby/padrino/padrino.dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM ruby:3.0
FROM ruby:3.4

WORKDIR /padrino
COPY app app
Expand All @@ -9,8 +9,11 @@ COPY config.ru config.ru
COPY Gemfile Gemfile
COPY Rakefile Rakefile

RUN bundle config set with 'puma'
RUN bundle install --jobs=4 --gemfile=/padrino/Gemfile

EXPOSE 8080

CMD ["bundle", "exec", "puma", "-C", "config/puma.rb", "-w", "8", "--preload"]
ENV RUBY_YJIT_ENABLE=1

CMD bundle exec puma -C config/puma.rb -w 8 --preload
Loading