Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reduce memory consumption in rake assets:precompile

Tags:

Problem:
I'm running out of RAM while performing the rake assets:precompile task in an automated build. Are there any strategies to do an incremental precompile, or in some other way perform the precompile stage without consuming as much RAM? It appears as though that task consumes around 850 MB more than the baseline for the build.

Context:
I'm trying to get a single Docker container Bitbucket Pipelines version of our automated build. Application stack includes Rails 4.2.7, PostgreSQL 9.3, Java 8, Maven 3.3.9 and JRuby 9.1.2.0. I've tried creating the image based off of Debian Jessie and also off of Alpine Linux, but it doesn't make much difference in the baseline memory.

like image 491
Toby Murray Avatar asked Jun 27 '16 22:06

Toby Murray


People also ask

What does rake assets Precompile do?

rake assets:precompile. We use rake assets:precompile to precompile our assets before pushing code to production. This command precompiles assets and places them under the public/assets directory in our Rails application.

How do I Precompile assets in Heroku?

To compile your assets locally, run the assets:precompile task locally on your app. Make sure to use the production environment so that the production version of your assets are generated. A public/assets directory will be created. Inside this directory you'll find a manifest.


1 Answers

Short answer

Use NodeJS as the JavaScript interpreter for precompiling (or another JavaScript interpreter characterized by low peak RAM usage).

Longer answer

For context, I'm using NodeJS 4.5.0 as compared to therubyracer v0.12.2 and therubyrhino v2.0.4

Can you increase RAM?

Sounds dumb, but before complicating the build process it may make sense to see if more capable build machines are available, or if swap space is available (although it will likely increase build times).

Can you switch JavaScript interpreters?

High peak RAM utilization seems to be a fundamental characteristic of both therubyrhino (Mozilla's Rhino JavaScript interpreter) and therubyracer (V8 JavaScript interpreter). There does not appear to be an effective way to significantly drop the amount of RAM consumed during the asset precompilation stage. The most viable paths appear to be precompiling the assets outside the build lifecycle and caching them somewhere so they can be fetched instead of precompiled, as suggested by @user4776684. As comments on the question suggest, both Rails version and Ruby version have an impact, but not nearly as much as the JavaScript interpreter.

If all else fails

As @slowjack2k mentioned above, if using Bundler, a parallel configuration can be leveraged to invoke NodeJS only for the precompile task and keep the original build relatively untouched. I didn't look into this as it was easier to switch interpreters, but while I was able to precompile the assets with rake and NodeJS, they didn't appear to be considered precompiled when it came to the rake + therubyrhino invocation so they were re-precompiled. I accomplished this with a programatically set BUNDLE_GEMFILE environment variable which pointed to a completely separate gemfile, which used MRI Ruby and NodeJS instead of JRuby and therubyrhino.

like image 86
Toby Murray Avatar answered Oct 11 '22 02:10

Toby Murray