Disable gems lookup on startup
On large react applications (~1000 chunks), i get some R10 errors because of the app isn't able to boot within 60 seconds.
Looking at the logs, it seems that the buildpack is trying to inject the configuration during this timeframe and it takes a few hundreds ms per file on average.
This is what a typical trace looks like
2021-01-06T22:53:04.296033+00:00 app[web.1]: Injecting runtime env into /app/build/static/js/358.214d2562.chunk.js (from .profile.d/inject_react_app_env.sh)
2021-01-06T22:53:04.512350+00:00 app[web.1]: Injecting runtime env into /app/build/static/js/359.3562496e.chunk.js (from .profile.d/inject_react_app_env.sh)
2021-01-06T22:53:04.682601+00:00 app[web.1]: Injecting runtime env into /app/build/static/js/36.74870549.chunk.js (from .profile.d/inject_react_app_env.sh)
2021-01-06T22:53:04.800934+00:00 app[web.1]: Injecting runtime env into /app/build/static/js/360.eb858927.chunk.js (from .profile.d/inject_react_app_env.sh)
2021-01-06T22:53:04.895693+00:00 app[web.1]: Injecting runtime env into /app/build/static/js/361.2907631a.chunk.js (from .profile.d/inject_react_app_env.sh)
2021-01-06T22:53:04.919483+00:00 heroku[web.1]: Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch
2021-01-06T22:53:04.936292+00:00 heroku[web.1]: Stopping process with SIGKILL
2021-01-06T22:53:05.003213+00:00 heroku[web.1]: Process exited with status 137
2021-01-06T22:53:05.048418+00:00 heroku[web.1]: State changed from starting to crashed
By looking at the script, it looks like it loads a new ruby VM for each files in the bundle, which can be really slow
ruby -E utf-8:utf-8 \
-r /app/.heroku/create-react-app/injectable_env.rb \
-e "InjectableEnv.replace('$js_bundle_filename')"
By disabling the loading of the gems on startup, i managed to decrease a bit the execution time for ruby-1.9.3 which is the version used by this buildpack:
ruby -E utf-8:utf-8 \
-r /app/.heroku/create-react-app/injectable_env.rb \
-e "InjectableEnv.replace('$js_bundle_filename')" \
--disable-gems
With the gems autoloading enabled (on a macbook pro with 4 cores and 1000 js files)
time .profile.d/inject_react_app_env.sh
.profile.d/inject_react_app_env.sh 13.07s user 6.86s system 90% cpu 22.003 total
Without:
time .profile.d/inject_react_app_env.sh
.profile.d/inject_react_app_env.sh 9.97s user 7.24s system 83% cpu 20.686 total
Fun fact, ruby 3.0 is way slower than 1.9.3 to start, so this patch is even more important
With gems:
time .profile.d/inject_react_app_env.sh
.profile.d/inject_react_app_env.sh 58.70s user 14.98s system 93% cpu 1:18.48 total
Without:
time .profile.d/inject_react_app_env.sh
.profile.d/inject_react_app_env.sh 12.23s user 8.16s system 84% cpu 24.011 total
My gut feeling is that on a typical dyno where the I/O are a bit slow than on my local machine, it can have a big impact and reduce the amount of time spent on the inject variable stage.
I will also try to reduce the number of files inspected in another PR.