Is my memory use on Heroku too high? (RoR, Puma, Heroku) - ruby-on-rails

I am getting an application set up on Heroku for production and have a hunch that my app's memory profile is quite big. I'm looking for a gut-check / benchmarks to understand whether my app is 'bloated' or not optimized for performance. I'm currently running 1 web dyno on Heroku with HireFire spinning up workers as needed for background tasks.
Current configuration:
puma.rb:
workers Integer(ENV['WEB_CONCURRENCY'] || 2) #
threads_count = Integer(ENV['MAX_THREADS'] || 5
threads threads_count, threads_count
preload_app!
rackup DefaultRackup
port ENV['PORT'] || 3000
environment ENV['RACK_ENV'] || 'development'
on_worker_boot do
# Worker specific setup for Rails 4.1+
# See: https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#on-worker-boot
ActiveRecord::Base.establish_connection
end
Procfile:
web: bundle exec puma -C config/puma.rb
worker: bundle exec rake jobs:work
Other relevant info:
- Using a CDN for assets
- Non-production gems are placed in development or test groups
- No caching set up (yet)
- Hobby basic DB
- Stack: cedar-14
Current Status / Performance Data:
PumaAutoTune Gem:
PumaAutoTune (33445s): All is well puma.resource_ram_mb=500.58154296875
puma.current_cluster_size=2
source=web.1 dyno=heroku.xxxx
sample#load_avg_1m=0.31 sample#load_avg_5m=0.14 sample#load_avg_15m=0.12
sample#memory_total=411.41MB sample#memory_rss=402.52MB
sample#memory_cache=5.36MB sample#memory_swap=3.54MB
sample#memory_pgpgin=1189542pages sample#memory_pgpgout=1085125pages
New Relic shows the following:
Blitz test results:
I have noticed that there's a difference in # of instances reported by PumaAutoTune for cluster size vs # of instances reported by New Relic. I'm not sure if both terms refer to the same idea.
Switching to a VPS is on the table but I'm expecting a significant learning curve there as I'm self-taught and quite a novice at this, so it's not an ideal short-term solution.

Related

Rails logs do not show anything in terminal for Puma when I try to hit the URL: localhost:3000

When I do rails s, it successfully starts my server, and serves the page through the URL http://localhost:3000, but the problem is: it doesn't show any changes when I access anything from this server.
I have accessed so many pages, but still it's not showing any hint. I have restarted the Rails server, have killed all the rails servers using:
ps aux | grep 'rails' | grep -v 'grep' | awk '{ print $2 }' | xargs kill -9
Have quit and started again iTerm but nothing is helping me.
I'm using Rails 5.0.0, and ruby 2.2.3.
There was a problem in config/puma.rb file, and it took me a night to figure this thing out. Anyway, the correct configuration for Puma while running your server for development is:
workers Integer(ENV['WEB_CONCURRENCY'] || 2)
threads_count = Integer(ENV['RAILS_MAX_THREADS'] || 5)
threads threads_count, threads_count
preload_app!
rackup DefaultRackup
port ENV['PORT'] || 3000
environment ENV['RACK_ENV'] || 'development'
on_worker_boot do
# Worker specific setup for Rails 4.1+
# See: https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#on-worker-boot
ActiveRecord::Base.establish_connection
end
I had the same problem. There was an error in puma.rb file and I figure out the problem by copying following content in puma.rb file. After that, restart your server and you can now find logs on any request on the server and also stop breakpoint on the server by mentioning breakpoint in you code, which was not possible with previous configuration.
# Code goes here
workers 2
# Min and Max threads per worker
threads 1, 6
app_dir = File.expand_path("../..", __FILE__)
shared_dir = "#{app_dir}/shared"
# Default to production
rails_env = ENV['RAILS_ENV'] || "production"
environment rails_env
# Set up socket location
bind "unix://#{shared_dir}/sockets/puma.sock"
# Logging
stdout_redirect "#{shared_dir}/log/puma.stdout.log", "#{shared_dir}/log/puma.stderr.log", true
# Set master PID and state locations
pidfile "#{shared_dir}/pids/puma.pid"
state_path "#{shared_dir}/pids/puma.state"
activate_control_app
Add this in development.rb file. I have my app on Rails 6.
config.logger = Logger.new(STDOUT)
In my case, thanks to #mick comment here my logs started appearing when I ran it through rails s (precisely bundle exec rails s).
I will update this answer later after debugging more on why is there a different, but a hunch is that running it through rails s would configure the logs output to be routed to STDOUT when the server is not running in daemonized mode.

Sinatra app in Rails 4.1 config

I want to fake an API with a little Sinatra app, following this method. Meaning I have a Rails app, and in the spec/support folder, a very simple Sinatra app:
module FakePrograms
class Application < Sinatra::Base
get "/API/V1/programs" do
{
programs: [
...
]
}.to_json
end
end
end
Part of the goal is to launch this app locally, so I can work on my Rails app with a fake API. Problem: when I do ruby spec/support/fake_programs.rb, the app can't boot, and I get a
config/puma.rb:14:in `block in _load_from':
uninitialized constant
#<Class:#<Puma::DSL:0x007fac0b0e0380>>::ActiveRecord (NameError)
Looks like Sinatra is booting using my Rails configuration. I don't need ActiveRecord nor Puma for my fake API.
I've read this question and this other one, but theese are in different context, because they need their Sinatra app to share routes with the Rails app.
Content of config/puma.rb:
workers Integer(ENV['WEB_CONCURRENCY'] || 2)
threads_count = Integer(ENV['MAX_THREADS'] || 5)
threads threads_count, threads_count
preload_app!
rackup DefaultRackup
port ENV['PORT'] || 3000
environment ENV['RACK_ENV'] || 'development'
on_worker_boot do
# Worker specific setup for Rails 4.1+
# See: https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#on-worker-boot
ActiveRecord::Base.establish_connection
end
I was looking at the config.ru file, but #max is right, it's not correlated.
The Puma README says:
By default, if no configuration file is specified, Puma will look for a configuration file at config/puma.rb.
Which is why your app is using this config file.
It goes on to say:
If you want to prevent Puma from looking for a configuration file in those locations, provide a dash as the argument to the -C (or --config) flag:
$ puma -C "-"
Since Puma can handle Sinatra apps directly, you could start your app like this:
$ puma -c "-" spec/support/fake_programs.rb
If you want to start your app using ruby with Puma as the built in server (as you are doing now), I think adding this to your Sinatra app should work (neither Sinatra’s :server_settings or Puma’s :config_files are very well documented):
set :server, 'puma'
set :server_settings, {:config_files => "-"}

Clustered puma not accepting more than 1 request concurrently

I have setup my puma web server based on heroku manual: Deploying Rails Applications with the Puma Web Server
config/puma.rb:
workers Integer(ENV['WEB_CONCURRENCY'] || 2)
threads_count = Integer(ENV['RAILS_MAX_THREADS'] || 2)
threads threads_count, threads_count
preload_app!
rackup DefaultRackup
port ENV['PORT'] || 3000
environment ENV['RACK_ENV'] || 'development'
on_worker_boot do
ActiveRecord::Base.establish_connection
end
Procfile contains:
web: bundle exec puma -C config/puma.rb
Now when I try to access action which has sleep 10 which delays the response and then try to access some other action, my understanding was that Puma would handle these 2 requests concurrently (since I have 2 workers). But instead it waits for the first request which sleeps to finish then it proceeds to the second one. Am i missing something?
My setup is:
Ruby 2.2.4
Rails 4.2.0
EDIT:
Ok, so I found out that on Heroku, it works, so question is, why it doesn't work in development mode?
rails s does not use the Procfile, you may want to look at using a tool like foreman: https://github.com/ddollar/foreman
update: this was the solution:
config.allow_concurrency = true in the rails development config.

RoR in Windows not working for pre-existing app built with RoR in linux

I've installed Ruby on Rails using RailsInstaller and also postgresql in Windows 8. I'm trying to run rails server using files for a pre existing app but I'm getting the error 'Worker mode not supported on JRuby or Windows'.
In my config/puma.rb file i've set workers to 0, then get an error about daemon mode not supported on windows. basically each time i change something i get more errors.
I've fixed up environment variables, gems, etc (like in other posts) such as this Cannot install Puma gem on Ruby on Rails. there any hope of running a pre-existing RoR app built in linux on a windows machine?
When I run rails server for the RoR 'blog' example it works fine, so I know that RoR is definitely working in windows!
This is my -'de-identified' config/puma.rb file. Is it because in windows I have no /var/app folder?? I've played around with directories etc to no avail.
`
#!/usr/bin/env puma
# start puma with:
# RAILS_ENV=production bundle exec puma -C ./config/puma.rb
workers 0
theident = 'nameofthing'
application_path = '/var/app/'+ theident + '.address.com.au/current'
railsenv = 'production'
directory application_path
environment railsenv
daemonize false
pidfile "#{application_path}/tmp/pids/puma-#{railsenv}.pid"
state_path "#{application_path}/tmp/pids/puma-#{railsenv}.state"
stdout_redirect"#{application_path}/log/puma-#{theident}.log"
threads 0, 16
bind "unix:///var/run/puma/" + theident + "_app.sock" `
I have changed those directories to the current path and now running 'rails server' starts going , but localhost:3000 is a page not working. I am getting errors around SIGUSR1 not working , SIGUSR2 not working ,etc
The "workers" method isn't supported for JRuby nor Windows, so the best solution would be to remove the line from puma.rb causing the error. In my case I removed;
workers Integer(ENV['WEB_CONCURRENCY'] || 2)
So remaining I have;
threads_count = Integer(ENV['RAILS_MAX_THREADS'] || 5)
threads threads_count, threads_count
preload_app!
rackup DefaultRackup
port ENV['PORT'] || 3000
environment ENV['RACK_ENV'] || 'development'
on_worker_boot do
# Worker specific setup for Rails 4.1+
# See: https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#on-worker-boot
ActiveRecord::Base.establish_connection
end
It might be different for you, but the specific line will start with "workers"

Memory Leak in rails app with ruby 2.3.0 and Puma 2.15.3

For some time I've been having a memory leak in my application. The current setup runs with Ruby 2.3.0, Rails 4.2 and Puma Webserver puma 2.15.3
It is recommended by Heroku to use Puma, however a lot of debugging has lead me to believe it's actual Puma Webserver which is the cause of all the troubles. During debugging I've removed most of the gems, code etc but the issue kept showing up, RAM Memory increasing until an out of memory showed up. This is why I'm 99,999% sure the leak isn't from my application. Next I installed "Thin" Webserver on my Development system and also this was not a solution. Then I also upgraded my ruby version to 2.3.0 and the leak was immediately solved, RAM usage stayed ok.
Due to this evolution, I upgraded my production system to Ruby 2.3.0 (thinking it was only a ruby version issue) but still I'm having the memory leak. I'm now at the point that it seems to be a combination of my Puma Webserver, together with Ruby 2.3.0...
Does anyone of you have any experience with Puma giving memory leaks with Ruby 2.3.0.
Thanks in advance,
T
UPDATE:
my puma.rb
workers Integer(ENV['WEB_CONCURRENCY'] || 2)
threads_count = Integer(ENV['MAX_THREADS'] || 5)
threads threads_count, threads_count
preload_app!
rackup DefaultRackup
port ENV['PORT'] || 3000
environment ENV['RACK_ENV'] || 'development'
on_worker_boot do
# Worker specific setup for Rails 4.1+
# See: https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server#on-worker-boot
ActiveRecord::Base.establish_connection
end

Resources