Application load time with large racks

I have a very very large rails app and have read every post on how to reduce load times, each suggesting cut back on tools or controllers or gems, but they are all used.

The problem I'm running into is heroku pushing error code R10 as my app takes over 60 seconds to load.

I tried one, almost successfully. I am trying to run Bundler.require and Application.inialize! in threads (the last thread is waiting for the first completion). The advantage of this is that the thin server boots up almost instantly.

The problem is that when someone makes a request to the application, the initialization process remains incomplete. Any idea how I can achieve this?

+3


source to share


2 answers


You can take control of the initialization process by extending the method initialize!

to config/application.rb

.

Take a look at the sample application.rb

file
from the github project. You must extend the method initialize!

inside the scope class Application < Rails::Application

.

You can use the basic methods from the Rails Initialization Docs under 2.3 railties / lib / rails / application.rb. So, this is what you get if you extend the methods and leave them as default.



class Application < Rails::Application
  def initialize!(group=:default) #:nodoc:
    raise "Application has been already initialized." if @initialized
    run_initializers(group, self)
    @initialized = true
    self
  end

  def run_initializers(group=:default, *args)
    return if instance_variable_defined?(:@ran)
    initializers.tsort_each do |initializer|
      initializer.run(*args) if initializer.belongs_to?(group)
    end
    @ran = true
  end
end

      

At this point, you can add print approvals and determine which part you are stuck on. For example, your variable is @initialized

never set to true

? If so, why? You may be stuck inside run_intializers

. If so, what initializer are you getting stuck inside?

0


source


I realized what I am trying to do, it is not possible. So I end the thread.

What I do: In my .rb environment,

def init_bundler

  # If you want your assets lazily compiled in production, use this line
  s = Time.now
  _rails_groups = (ENV["RAILS_GROUPS"]||"").split(",")
  if _rails_groups.length == 1 and _rails_groups.first.to_s == "assets"
    Bundler.require(:assets)  #load ONLY assets .. 
  elsif _rails_groups.length == 1 and _rails_groups.first.to_s == "clock"
    Bundler.require(:clock)  #load ONLY assets .. 
  else
    Bundler.require(:default, *_rails_groups, Rails.env.to_s)
  end
  puts "bundler required in #{Time.now - s}s"
end

puts "starting t1"
$_t1 = Thread.new{ init_bundler }

      

In my environment .rb:



def init_app
  # Initialize the rails application
  puts "initialize started"
  s = Time.now
  Hedgepo::Application.initialize!
  puts "initialize done in #{Time.now - s}s"

end

puts "starting t2"
$_t2 = Thread.new do 
  loop do 
    if defined?($_t1) and !$_t1.status
      init_app
      break
    else
      puts "waiting for bundler"
    end
    sleep(1)
  end
end

      

the middleware I'm using above all the others:

class MyInit
  def initialize(app)
    @app = app
  end

  def call(env)
    loop do 
      if defined?($_t2) and !$_t2.status
        break
      else
        puts "waiting for app init to finish...."
      end
      sleep(1)
    end
    @app.call(env)
  end
end

      

But the problem is that Rack :: Server allocates the "app" variable and .start! s server when hit is hit. So no matter what I do, I cannot change the application that was initialized BEFORE this @app variable was populated.

-1


source







All Articles