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

Exclude specific files to prevent build to fail with "FATAL ERROR: CALL_AND_RETRY_LAST" #4055

Closed
tschoartschi opened this issue May 12, 2015 · 35 comments

Comments

@tschoartschi
Copy link

Hey!

We are using ember-cli since almost over a year and it always worked great. Today we encountered an issue when building our app on Jenkins in production environment. It seems we are hitting some memory limit of node.js or more specifically a limit of V8. During the build the error "FATAL ERROR: CALL_AND_RETRY_LAST" is displayed and then the build is aborted. We don't know how to resolve this issue. Maybe you can help us fixing this problem.

The exact output on the console looks as follows:

+ ember build --environment production
version: 0.2.3
Could not find watchman, falling back to NodeWatcher for file system events.
Visit http://www.ember-cli.com/#watchman for more info.
BuildingBuilding.Building..Building...BuildingBuilding.Building..FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory

Our package.json:

  "devDependencies": {
    "broccoli-asset-rev": "^2.0.2",
    "broccoli-manifest": "0.0.5",
    "broccoli-merge-trees": "^0.2.1",
    "broccoli-static-compiler": "^0.2.1",
    "broccoli-string-replace": "0.0.2",
    "ember-cli": "0.2.3",
    "ember-cli-app-version": "0.3.3",
    "ember-cli-autoprefixer": "^0.3.0",
    "ember-cli-babel": "^5.0.0",
    "ember-cli-content-security-policy": "0.4.0",
    "ember-cli-dependency-checker": "0.0.8",
    "ember-cli-eslint": "0.2.4",
    "ember-cli-htmlbars": "0.7.6",
    "ember-cli-ic-ajax": "0.1.1",
    "ember-cli-inject-live-reload": "^1.3.0",
    "ember-cli-mocha": "0.6.0",
    "ember-cli-sass": "4.0.0-beta.5",
    "ember-cli-selectize": "0.3.1",
    "ember-cli-simple-auth": "0.7.3",
    "ember-cli-uglify": "1.0.1",
    "ember-data": "1.0.0-beta.16.1",
    "ember-export-application-global": "^1.0.2",
    "ember-i18n": "^3.1.0",
    "eslint": "^0.20.0",
    "eslint-plugin-ember": "^1.0.1"
  }
@jschilli
Copy link
Contributor

We crossed some threshold as well (in uglify I would guess) and in the heat of battle started using the following:

node --max-old-space-size=1900 node_modules/ember-cli/bin/ember build --environment production

HTH

On May 12, 2015, at 5:07 AM, tschoartschi notifications@github.com wrote:

Hey!

We are using ember-cli since almost over a year and it always worked great. Today we encountered an issue when building our app on Jenkins in production environment. It seems we are hitting some memory limit of node.js or more specifically a limit of V8. During the build the error "FATAL ERROR: CALL_AND_RETRY_LAST" is displayed and then the build is aborted. We don't know how to resolve this issue. Maybe you can help us fixing this problem.

The exact output on the console looks as follows:

  • ember build --environment production
    version: 0.2.3
    Could not find watchman, falling back to NodeWatcher for file system events.
    Visit http://www.ember-cli.com/#watchman for more info.
    BuildingBuilding.Building..Building...BuildingBuilding.Building..FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - process out of memory
    Our package.json:

    "devDependencies": {
    "broccoli-asset-rev": "^2.0.2",
    "broccoli-manifest": "0.0.5",
    "broccoli-merge-trees": "^0.2.1",
    "broccoli-static-compiler": "^0.2.1",
    "broccoli-string-replace": "0.0.2",
    "ember-cli": "0.2.3",
    "ember-cli-app-version": "0.3.3",
    "ember-cli-autoprefixer": "^0.3.0",
    "ember-cli-babel": "^5.0.0",
    "ember-cli-content-security-policy": "0.4.0",
    "ember-cli-dependency-checker": "0.0.8",
    "ember-cli-eslint": "0.2.4",
    "ember-cli-htmlbars": "0.7.6",
    "ember-cli-ic-ajax": "0.1.1",
    "ember-cli-inject-live-reload": "^1.3.0",
    "ember-cli-mocha": "0.6.0",
    "ember-cli-sass": "4.0.0-beta.5",
    "ember-cli-selectize": "0.3.1",
    "ember-cli-simple-auth": "0.7.3",
    "ember-cli-uglify": "1.0.1",
    "ember-data": "1.0.0-beta.16.1",
    "ember-export-application-global": "^1.0.2",
    "ember-i18n": "^3.1.0",
    "eslint": "^0.20.0",
    "eslint-plugin-ember": "^1.0.1"
    }

    Reply to this email directly or view it on GitHub Exclude specific files to prevent build to fail with "FATAL ERROR: CALL_AND_RETRY_LAST" #4055.

@tschoartschi
Copy link
Author

@jschilli Thank you for the hint :) but there is something really odd... because --max-old-space-size=2400 is still too less. --max-old-space-size=5000 results in a never ending script (It runs since you posted the answer). Hope the issue can be resolved. It is quite urgent because we wanted to release a new version of our app today :p

EDIT: now, after more than 4 hours the build failed with --max-old-space-size=5000 with the same error... any ideas how we could track down this issue?

@tschoartschi
Copy link
Author

Okay, I was able to trace down the problem. We are using code which is compiled for multiple platforms. The source code is C++ and is transpiled to emscripten (Javascript). The emscripten files are quite large and we load it on demand. But we put it into the assets folder to have it in "application cache manifest".

When I remove the emscripten files, the build makes no problem and we can build without the --max-old-space-size

Whats happening with the files which are located in public/assets while building the ember-cli app in production mode? Is there any way to tell ember-cli to not do things with the emscripten files, which crashes the build?

Moving the files from the assets folder to another folder would be an option but it's not the best option for us, because there are many people involved who would have to update their paths.

Any ideas how we could resolve this issue?

@jschilli
Copy link
Contributor

I would imagine that uglify is complicit here.

see http://www.ember-cli.com/asset-compilation/ http://www.ember-cli.com/asset-compilation/ for how to disable minification.

if that works you can then evaluate how to exclude the emscripten file from uglification

On May 13, 2015, at 6:37 AM, tschoartschi notifications@github.com wrote:

Okay, I was able to trace down the problem. We are using code which is compiled for multiple platforms. The source code is C++ and is transpiled to emscripten (Javascript). The emscripten files are quite large and we load it on demand. But we put it into the assets folder to have it in "application cache manifest".

When I remove the emscripten files, the build makes no problem and we can build without the --max-old-space-size

Whats happening with the files which are located in public/assets while building the ember-cli app in production mode? Is there any way to tell ember-cli to not do things with the emscripten files, which crashes the build?

Moving the files from the assets folder to another folder would be an option but it's not the best option for us, because there are many people involved who would have to update their paths.

Any ideas how we could resolve this issue?


Reply to this email directly or view it on GitHub #4055 (comment).

@tschoartschi
Copy link
Author

@jschilli yes it is uglification. But I don't want to turn off uglification for all of my files... Right now I didn't find any way to exclude just the emscripten files from uglification. Has anyone an idea?

@tschoartschi tschoartschi changed the title Building in production causes node error "FATAL ERROR: CALL_AND_RETRY_LAST" Exclude specific files to prevent build to fail with "FATAL ERROR: CALL_AND_RETRY_LAST" May 13, 2015
@tschoartschi
Copy link
Author

We still don't have a good solution... now we just put the emscripten files into a directory which ember-cli don't know (we call it emscripten_components) and for deployment we need to copy these files manually. This doesn't feel like a real solution but it works for now.

If someone has a better suggestion let me know. Meanwhile I opened a thread on disucss.ember.com because I think our problem is not really an issue with ember-cli.

@stefanpenner
Copy link
Contributor

what version of node are you using on jenkins server

@jschilli
Copy link
Contributor

We are on 0.12.1 IIRC

On May 19, 2015, at 11:31 AM, Stefan Penner notifications@github.com wrote:

what version of node are you using on jenkins server


Reply to this email directly or view it on GitHub #4055 (comment).

@stefanpenner
Copy link
Contributor

cc @chadhietala this will likely be something the packager work will enable nicely

@tschoartschi
Copy link
Author

@stefanpenner we are on node 0.12.2, but an option to exclude specific files from the build (especially uglification) would be great 👍 For us, minifying or uglifying the emscripten files again makes no sense. In our case it just slows down the build process and now even made it impossible.
But for now there is no better solution than copying the files manually?

@stefanpenner
Copy link
Contributor

But for now there is no better solution than copying the files manually?

leave them in public/ and they should just passthrough

@stefanpenner
Copy link
Contributor

in theory adding file exclude/include support to https://github.com/ef4/broccoli-uglify-sourcemap/blob/master/index.js would also help fix this.

@tschoartschi
Copy link
Author

@stefanpenner leaving them in public (and not put them into the assets folder) seems to work 👍 I'll check that in more detail tomorrow :-)

@stefanpenner
Copy link
Contributor

@stefanpenner leaving them in public (and not put them into the assets folder) seems to work I'll check that in more detail tomorrow :-)

👍

Awesome, but like I said, i think the packager work will expose more flexibility to this part of the build. Stay tunned

@tschoartschi
Copy link
Author

@stefanpenner I was to enthusiastic yesterday. I think I made a typo when trying to run "ember build --environment production". Just putting the emscripten files outside of the assets folder didn't help. I implemented an in-repo-addon which does the copying stuff. Folder structure looks as follows:

  • app
    • controllers
    • ....
  • public
    • assets
      • // NO EMSCRIPTEN HERE
      • ....
    • // NO EMSCRIPTEN HERE
  • emscripten_components
    • // THE PLACE TO PUT ALL EMSCRIPTEN
  • dist

At first I tried to add some express middleware to serve files from emscripten_components but I didn't managed it to work. So I decided to copy the emscripten into the public folder when I'm in development mode and otherwise copy it into dist folder. If someone needs the same thing or a place to start, here is my in-repo-addon (yes I know it's not a super clean solution, I know it is not generic and yes I know it is just a hack ;-) but it works. If someone has tips or tricks I'm happy to hear from you).
One thing to mention is that you can not run "ember build --environment production" when in another terminal "ember serve" is running. This restriction is OK for me right now because I only do the production build on our Jenkins.

var fse = require('fs-extra');
var path = require('path');

var config = require('../../config/environment');

module.exports = {
    name: 'emscripten-handling',

    src: '',
    distDev: '',

    isDevelopingAddon: function () {
        return true;
    },

    preBuild: function () {
        console.log('[EMSCRIPTEN HANDLING] Warning: make sure there is no other build running!! Check ember serve also');
        this.setPaths();
        if (!this.isDevelopment()) {
            if (fse.existsSync(this.distDev)) {
                fse.removeSync(this.distDev);
            }
            return;
        }
        if (!fse.existsSync(this.distDev)) {
            fse.mkdirsSync(this.distDev);
        }
        console.log('[EMSCRIPTEN HANDLING] preBuild copy to folders');
        fse.copySync(this.src, this.distDev);
    },

    postBuild: function (result) {
        if (this.isDevelopment()) {
            return;
        }
        this.setPaths();
        fse.copySync(this.src, result.directory + '/' + this.getEmscriptenAppComponentFolder());
    },

    setPaths: function () {
        var env = process.env.EMBER_ENV;
        var actualConfig = config(env);
        this.src = actualConfig.APP.EMSCRIPTEN_APP_COMPONENT_FOLDER;
        this.distDev = 'public/' + actualConfig.APP.EMSCRIPTEN_APP_COMPONENT_FOLDER;
    },

    getEmscriptenAppComponentFolder: function () {
        var env = process.env.EMBER_ENV;
        var actualConfig = config(env);
        return actualConfig.APP.EMSCRIPTEN_APP_COMPONENT_FOLDER;
    },

    isDevelopment: function () {
        return process.env.EMBER_ENV === 'development';
    }
};

@marcelbwaste
Copy link

@stefanpenner Is there any news on this topic? I am experiencing the same trouble. I added a large, already minified js file which causes the ember build to go from two to ninety minutes.

@stefanpenner
Copy link
Contributor

@stefanpenner Is there any news on this topic? I am experiencing the same trouble. I added a large, already minified js file which causes the ember build to go from two to ninety minutes.

nothing yet. Although, sounds like you should just move that file into public, and not send it through another minification step.

@marcelbwaste
Copy link

@stefanpenner Thank you for the reply. I tried moving the file to the public folder, however in a production build it still seems to do some labor intensive things (I guess uglification) to it because the build is still taking about ninety minutes.

@marcelbwaste
Copy link

@stefanpenner It actually seems to be the compression done by broccoli-uglify-js which is taking so much time. Since it is not supported to disable this for some files, I have disabled this for the whole application in Brocfile.js:

var app = new EmberApp({
            minifyJS: {
                options: {
                    compress: false
                }
            }
        });

@stefanpenner
Copy link
Contributor

Since it is not supported to disable this for some files, I have disabled this for the whole application in Brocfile.js:

we should likely do the following:

  • allow minifyJS to take include/exclude globs
  • have minifyJS log when a file took more the some threshold to minify.

@tschoartschi
Copy link
Author

@stefanpenner Thanks a lot for your effort! I wanted to ask if there are any news on this issue?

@felipemartim
Copy link

allow minifyJS to take include/exclude globs

+1

@stefanpenner
Copy link
Contributor

@stefanpenner Thanks a lot for your effort! I wanted to ask if there are any news on this issue?

Sorry not yet

@stefanpenner
Copy link
Contributor

for those interested, come help populate the stress app ember-cli/stress-app#2

@kjhangiani
Copy link

Exclude/include on uglify has become essential for us too, resorting to some mega hacks to get around the lack of exclude. Adding something like tiny mce bumps the build up to about twenty minutes when all that is required is a passthrough copy.

Definitely need some way to tell ember that specific files are passthrough only, as otherwise the build gets out of control unnecessarily

@stefanpenner
Copy link
Contributor

I believe the feature only needs to be added to the upstream dependency: https://github.com/ef4/broccoli-uglify-sourcemap

Basically just: check opts.blacklist here and skip the minify step if matched.

It may be nice to make the blacklist support globs, but not a requirement (that can be added later)

I don't think I have time, but it should be relatively easy for someone to land what i describe above.

@kjhangiani
Copy link

@stefanpenner thanks for the heads up, that doesn't look too bad.

I'm going to spend an hour or two and see what I can come up with. glob or glob-like syntax is probably necessary to make this a useful feature.

Does ember-cli/broccoli etc have a preferred glob library? Can I add a dependency for it, or is there an existing way to include that functionality in this module?

@stefanpenner
Copy link
Contributor

Does ember-cli/broccoli etc have a preferred glob library? Can I add a dependency for it, or is there an existing way to include that functionality in this module?

minimatch we use it via https://github.com/joliss/node-walk-sync

@kjhangiani
Copy link

Sorry I didn't see your edit until now, probably not too hard to switch it to node-walk-sync but I ended up using minimatch anyway.

It seems to work on our build, here is the squashed commit:

soxhub/broccoli-uglify-sourcemap@d33fe38

accepts an exclude: [] parameter to minifyJS: {}, an array of globs to check against.

I did also discover that another major bottleneck in our build is in using broccoli-funnel to pickFiles, even though all we are doing is a straight copy (of bower_components/tinymce to assets/tinymce)... Funnel seems to be doing its own sort of processing (and tinymce has tons of files in it).

Is there a better way to copy an entire directory from bower_components without Funnel? Moving this to a post build addon seems much more performant

@stefanpenner
Copy link
Contributor

Funnel seems to be doing its own sort of processing (and tinymce has tons of files in it).

funnel has the ability to merely link in entire trees, i suggest that might be the approach you wan to take.

https://github.com/broccolijs/broccoli-funnel/blob/master/index.js#L102-L104

@stefanpenner
Copy link
Contributor

I also have a POC (nearly ready to primetime – merely lacking support for windows users without symlinks) that dramatically improves performance of funnel even in crazy circumstances hjdivad/broccoli-funnel#2

The work there is meant as the foundation for planned dramatic perf boosts to broccoli-filter broccoli-persistent-filter broccoli-merge-trees etc.

@kjhangiani
Copy link

Yeah, I just removed the include: [] parameter from my Funnel() (it was basically collecting everything anyway), and this seems to have sped up the build a lot, in conjunction with the new exclude param on ugilify, build times are normal again.

Thanks for the help! Should I submit that commit as a PR or something? TBH I've never really submitted a PR before so not even sure how to go about it lol

@stefanpenner
Copy link
Contributor

@kjhangiani yup PR sounds good. a TL;DR if you have questions can be found here

@kjhangiani
Copy link

@stefanpenner thanks, submitted

@stefanpenner
Copy link
Contributor

passing exclude information to uglfier is now fully supported.
Debug logging even includes some extra hints.
closing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants