How to debug a Rails asset precompile which is unbearably slow

后端 未结 3 1174
遥遥无期
遥遥无期 2021-01-30 13:09

I\'m working on a Rails 3.2 project and the assets have increased a fair bit in recent months although I wouldn\'t consider the project to be large. The assets consist of JS (no

相关标签:
3条回答
  • 2021-01-30 13:46

    there is a bunch of possible causes to this issue.

    for a possible cause, i would like to know how the time of compiling the assets increased in the several environments for your last deploys. this might indicate if the problem is just on the environments or within the asset compilation itself. you could use git bisect for that. i usually have my apps deployed to staging via a jenkins or another ci system so that i can see any variations in deploy time and when they were introduced.

    it might boil down to extensive use of resources CPU, MEMORY (any swap?), IO. if you compile the assets on the production systems they might be busy serving your applications request. go to your system, do a top for resources, maybe there are too many file handles at the same time (lsof is good for that).

    another thing might be that you load or cache some data for your application. databases are usually much larger in staging and production environments then they are on dev boxes. you could just put some Rails.logger calls in your initializers or whaterver.

    0 讨论(0)
  • 2021-01-30 13:51

    This may not entirely answer your question, but I believe it is a decent enough start. As you'll see, the precise answer will depend on the individual application, gem versions and so on.

    So. For asset-related work, as you know, Rails uses a library called Sprockets, which in newer versions of Rails is, I believe, hooked into Rails as a Railtie. It initializes a Sprockets "environment" that can do things like look at your asset manifest, load those files, compress them, give the compiled assets sensible names, etc.

    By default, that Sprockets::Environment logs its activity to STDERR with a log level of FATAL, which isn't very useful in these situations. Fortunately, the Sprockets::Environment (as of 2.2.2) has a writeable logger attribute that you can patch in via Rails, using an initializer.


    So, here's what I suggest, to start:

    In config/initializers, create a file, something like asset_logging.rb. In it, put:

    Rails.application.config.assets.logger = Logger.new($stdout)
    

    This overwrites the default logger with one that will spit more information out to STDOUT. Once you've got this set up, then run your asset pre-compilation task:

    rake RAILS_ENV=production assets:precompile
    

    And you should see slightly more interesting output, such as:

    ...
    Compiled jquery.ui.core.js  (0ms)  (pid 66524)
    Compiled jquery.ui.widget.js  (0ms)  (pid 66524)
    Compiled jquery.ui.accordion.js  (10ms)  (pid 66524)
    ...
    

    But, in the end, the final answer will depend on:

    • how "deep" you want to go with logging this asset stuff
    • what specific version of Rails, Sprockets, etc. you're using
    • and what you find along the way

    As you've already learned, log spelunking at the Rake task level, or even at the Rails level, doesn't give much information. And even making Sprockets itself verbose (see above) doesn't tell you too terribly much.

    If you wanted to go deeper than Sprockets, you can probably monkey patch the various engines and processors that Sprockets dutifully chains together to make the asset pipeline work. For example, you could look into the logging capabilities of these components:

    • Sass::Engine (converts SASS to CSS)
    • Uglifier (JavaScript compressor wrapper)
    • ExecJS (runs JavaScript in Ruby; a dependency of both Sprockets and Uglifier)
    • therubyracer (V8 embedded in Ruby; used by ExecJS)
    • etc.

    But I will leave all that as "an exercise for the reader." If there's a silver bullet, I'd certainly like to know about it!

    0 讨论(0)
  • 2021-01-30 13:55

    I think you need to see the cpu usage parameters on your Prod server.

    Moreover, there may be a possibility that assets are getting precompiled multiple times. I would suggest creating a assets directory in shared directory created by capistrano, copying your changes in the same and link it to your apps while deploying.

    Heres how I do it,

      after "deploy:update_code" do
        run "export RAILS_ENV=production"
        run "ln -nfs #{shared_path}/public/assets #{release_path}/public/assets"
        # Also for logs and temp section.
        # run "ln -nfs #{shared_path}/log #{release_path}/log"
        # run "ln -nfs #{shared_path}/tmp #{release_path}/tmp"
        #sudo "chmod -R 0777 #{release_path}/tmp/"
        #sudo "chmod -R 0777 #{release_path}/log/"
      end
    
    0 讨论(0)
提交回复
热议问题