My blog post earlier this month about what causes Ruby memory bloat, and about a way to potentially reduce memory usage by 70%, triggered quite a storm in the community! It's clear that I stumbled upon a significant pain point.
Ruby apps can use a lot of memory. But why? Various people in the community attribute it to memory fragmentation, and provide two “hacky” solutions. Dissatisfied by the current explanations and provided solutions, I set out on a journey to discover the deeper truth and to find better solutions.
When developing a Rails app, have there been times when you’re wondering “what properties/columns does this model have”? The easiest way to find out is by inspecting db/schema.rb, but that gets annoying quickly. If only there’s a way to keep your schema closer to you. Enter the annotate gem.
Selenium + Chrome Headless fail with mysterious errors when run in GitLab CI and Docker. Here’s why, and also how we fixed it.
People who have upgraded to macOS High Sierra and who are using a preforking app server such as Puma or Unicorn (with the right settings), may have noticed this error:
objc: +[__NSPlaceholderDictionary initialize] may have been in progress in another thread when fork() was called. We cannot safely call it or ignore it in the fork() child process. Crashing instead. Set a breakpoint on objc_initializeAfterForkError to debug.
This cryptic error is triggered under the following conditions:
- You are using Unicorn with
preload_app, or Puma in cluster mode, or iodine in prefork mode, or Passenger in smart spawning mode.
- And you are using MRI.
- And your application uses a gem that is either directly or indirectly linked to the macOS Foundation framework.
This error is caused by changes in how
fork() behaves in High Sierra. This article covers:
- What is this and why did Apple change it?
- How are the Puma, Unicorn and Passenger authors responding to this?
- What can you do about it, and do you need to do anything at all?
- What should the wider Ruby ecosystem do?