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

add RAILS_MIN_THREADS, RAILS_MAX_THREADS, set default worker, preload… #2143

Merged
merged 17 commits into from Apr 21, 2020
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 5 additions & 1 deletion History.md
Expand Up @@ -13,7 +13,11 @@
* Deprecations, Removals and Breaking API Changes
* `Puma.stats` now returns a Hash instead of a JSON string (#2086)
* `--control` has been removed. Use `--control-url` (#1487)
* `worker_directory` has been removed. Use `directory`.
* `worker_directory` has been removed. Use `directory`
* min_threads now set by environment variables PUMA_MIN_THREADS and MIN_THREADS
* max_threads now set by environment variables PUMA_MAX_THREADS and MAX_THREADS
* max_threads default to 5 in MRI or 16 for all other interpretters
* preload by default if workers > 1 and interpretter supports workers
* `tcp_mode` has been removed without replacement. (#2169)
* Daemonization has been removed without replacement. (#2170)
* Changed #connected_port to #connected_ports (#2076)
Expand Down
15 changes: 12 additions & 3 deletions lib/puma/configuration.rb
Expand Up @@ -137,6 +137,11 @@ def initialize(user_options={}, default_options = {}, &block)
@file_dsl = DSL.new(@options.file_options, self)
@default_dsl = DSL.new(@options.default_options, self)


if !@options[:prune_bundler]
default_options[:preload_app] = (@options[:workers] > 1) && ::Process.respond_to?(:fork)
end

if block
configure(&block)
end
Expand Down Expand Up @@ -167,14 +172,18 @@ def flatten!
self
end

def default_max_threads
Puma.mri? ? 5 : 16
end

def puma_default_options
{
:min_threads => 0,
:max_threads => 16,
:min_threads => Integer(ENV['PUMA_MIN_THREADS'] || ENV['MIN_THREADS'] || 0),
:max_threads => Integer(ENV['PUMA_MAX_THREADS'] || ENV['MAX_THREADS'] || default_max_threads),
:log_requests => false,
:debug => false,
:binds => ["tcp://#{DefaultTCPHost}:#{DefaultTCPPort}"],
:workers => 0,
:workers => Integer(ENV['WEB_CONCURRENCY'] || 0),
:mode => :http,
:worker_timeout => DefaultWorkerTimeout,
:worker_boot_timeout => DefaultWorkerTimeout,
Expand Down
10 changes: 10 additions & 0 deletions lib/puma/detect.rb
Expand Up @@ -12,4 +12,14 @@ def self.jruby?
def self.windows?
IS_WINDOWS
end

IS_TRUFFLE = RUBY_PLATFORM == 'truffleruby'

def self.truffle?
IS_TRUFFLE
end

def self.mri?
RUBY_ENGINE == 'ruby' || RUBY_ENGINE.nil?
end
end
2 changes: 1 addition & 1 deletion lib/puma/plugin.rb
Expand Up @@ -109,7 +109,7 @@ def in_background(&blk)
end

def workers_supported?
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This method feels like it should be in the lib/puma/detect.rb

Copy link
Contributor Author

Choose a reason for hiding this comment

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

return false if Puma.jruby? || Puma.windows?
return false if Puma.jruby? || Puma.windows? || Puma.truffle?
Copy link
Contributor Author

Choose a reason for hiding this comment

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

should we check ::Process.respond_to?(:fork) as well?
Does that single check eliminate the need to check for jruby/windows/truffle?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Member

Choose a reason for hiding this comment

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

Fixed in my nitpick commit. Thanks for the work on this PR!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sweet!

true
end
end
Expand Down
9 changes: 6 additions & 3 deletions test/test_cli.rb
Expand Up @@ -55,7 +55,8 @@ def test_control_for_tcp
body = s.read
s.close

assert_match(/{"started_at":"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z","backlog":0,"running":0,"pool_capacity":16,"max_threads":16,"requests_count":0}/, body.split(/\r?\n/).last)
dmt = Puma::Configuration.new.default_max_threads
assert_match(/{"started_at":"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z","backlog":0,"running":0,"pool_capacity":#{dmt},"max_threads":#{dmt},"requests_count":0}/, body.split(/\r?\n/).last)

ensure
cli.launcher.stop
Expand Down Expand Up @@ -89,7 +90,8 @@ def test_control_for_ssl
body = http.request(req).body
end

expected_stats = /{"started_at":"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z","backlog":0,"running":0,"pool_capacity":16,"max_threads":16,"requests_count":0}/
dmt = Puma::Configuration.new.default_max_threads
expected_stats = /{"started_at":"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z","backlog":0,"running":0,"pool_capacity":#{dmt},"max_threads":#{dmt}/
assert_match(expected_stats, body.split(/\r?\n/).last)
assert_equal([:started_at, :backlog, :running, :pool_capacity, :max_threads, :requests_count], Puma.stats.keys)

Expand Down Expand Up @@ -169,7 +171,8 @@ def test_control
body = s.read
s.close

assert_match(/{"started_at":"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z","backlog":0,"running":0,"pool_capacity":16,"max_threads":16,"requests_count":0}/, body.split("\r\n").last)
dmt = Puma::Configuration.new.default_max_threads
assert_match(/{"started_at":"\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z","backlog":0,"running":0,"pool_capacity":#{dmt},"max_threads":#{dmt},"requests_count":0}/, body.split("\r\n").last)
ensure
if UNIX_SKT_EXIST
cli.launcher.stop
Expand Down
67 changes: 67 additions & 0 deletions test/test_config.rb
Expand Up @@ -6,9 +6,17 @@
require "puma/configuration"
require 'puma/events'


class TestConfigFile < TestConfigFileBase
parallelize_me!

def test_default_max_threads
max_threads = 16
max_threads = 5 if RUBY_ENGINE.nil? || RUBY_ENGINE == 'ruby'
assert_equal max_threads, Puma::Configuration.new.default_max_threads
end


def test_app_from_rackup
conf = Puma::Configuration.new do |c|
c.rackup "test/rackup/hello-bind.ru"
Expand Down Expand Up @@ -275,6 +283,65 @@ def test_double_bind_port
end
end

class TestConfigEnvVariables < TestConfigFileBase
def test_config_loads_correct_min_threads
conf = Puma::Configuration.new
assert_equal 0, conf.options.default_options[:min_threads]

with_env("MIN_THREADS" => "7") do
conf = Puma::Configuration.new
assert_equal 7, conf.options.default_options[:min_threads]
end

with_env("PUMA_MIN_THREADS" => "8") do
conf = Puma::Configuration.new
assert_equal 8, conf.options.default_options[:min_threads]
end
end

def test_config_loads_correct_max_threads
conf = Puma::Configuration.new
assert_equal conf.default_max_threads, conf.options.default_options[:max_threads]

with_env("MAX_THREADS" => "7") do
conf = Puma::Configuration.new
assert_equal 7, conf.options.default_options[:max_threads]
end

with_env("PUMA_MAX_THREADS" => "8") do
conf = Puma::Configuration.new
assert_equal 8, conf.options.default_options[:max_threads]
end
end

def test_config_does_not_load_workers_by_default
conf = Puma::Configuration.new
assert_equal 0, conf.options.default_options[:workers]
end

def test_config_loads_workers_from_env
with_env("WEB_CONCURRENCY" => "9") do
conf = Puma::Configuration.new
assert_equal 9, conf.options.default_options[:workers]
end
end

def test_config_does_not_preload_app_if_using_workers
with_env("WEB_CONCURRENCY" => "0") do
conf = Puma::Configuration.new
assert_equal false, conf.options.default_options[:preload_app]
end
end

def test_config_preloads_app_if_using_workers
with_env("WEB_CONCURRENCY" => "2") do
preload = Puma::Plugin.new.workers_supported?
conf = Puma::Configuration.new
assert_equal preload, conf.options.default_options[:preload_app]
end
end
end

class TestConfigFileWithFakeEnv < TestConfigFileBase
def setup
FileUtils.mkpath("config/puma")
Expand Down