Railsberry ∞
I have such a massive lump of regret in my stomach right now for not going to this conference!
the home of @whalesalad, a designer
hacker & vagabond living in Sweden
You're browsing posts tagged with Ruby. Return to safety ↩
I have such a massive lump of regret in my stomach right now for not going to this conference!
I'm really loving Ruby these days. A lot. Today's tip: quickly get a sum of all the elements inside an array, using our buddy from Enumerable: inject.
Take a look at the following code:
x = [1, 5, 3, 0, 10]
x.inject :+
=> 19
So clean! Check out the full documentation for the inject/reduce methods on Enumerable. Learn them! Use them! Profit! $$$
This is exciting to see! It's only a preview release, but cool nonetheless. The final 2.0.0 is expected to come out towards the end of February.
1.9.3-p286 was just released and i'm still on 1.9.3-p194 due to the enhancements that can be made to it that speed up startup time and add garbage collection.
Speaking of speed, it looks like there has been even more development in that arena, with some new patches that supposedly cut Rails boot time in half. More info on that.
Looks like i'll be building some rubies this weekend! Follow the title to see the release notes for the 2.0.0 preview.
Note: This has been updated for Ruby 1.9.3-p327, the latest as of the update.
I've been a Python + Django developer since the dawn of time. Okay not really, but for the last 5 or so years. One of the things I frequently referred to when talking about Rails with other developers was the fact that booting the development environment took forever. Particularly on larger projects or where you're a noob and can't forsee the consequences of relying on tons of external dependencies.
Well... I've gone to the dark-side. I'm a Rails developer now. I'll list my reasons why another time, but it's safe to say that I am using it for all of my new projects -- this site included.
Recently some effort has been put into speeding up the rails development environment. It's not nearly as bad as it used to be. That being said, as your project grows and you rely on more gems and modifications to the components initialized on Rails boot, it starts to slow down.
Until recently, there hasn't been much you can do about it:

Note: The sloth is my favorite animal. You maybe wondering, "Well Michael, if you're such a fan of the slowest animal alive, it's no wonder you're a Ruby programmer!" Hah! Funny!
Right this second, I can evaluate the amount of time that it takes my rails environment to boot. I do this with the following command:
% time rails r 'puts 1'
1
rails r 'puts 1' 2.63s user 0.37s system 99% cpu 3.008 total
What's this doing? We're using the rails runner command or rails r for short to run the simple command puts 1. Essentually, this runs the command inside of the rails environment. Prefixing this with the time command let's us observe the total time used for this task. Looks like a little over 3 seconds. Not bad, but this is a fairly new project (the API for a current stealth project of mine)
Let's try the same thing on another project, a fairly typical Rails project called Ask Herzl, which we just deployed at New Signature.
% time rails r "puts 1"
Connecting to database specified by database.yml
1
rails r "puts 1" 4.23s user 1.19s system 54% cpu 10.009 total
As you can see, this takes quite a bit longer. 10 seconds total. Every time you run rails console, rails server, rake db:migrate etc… you're going to be sitting there for at least 10 seconds before anything even happens.
Sokolov Yura (funny-falcon) has contributed some radical patches to Ruby 1.9.3-p194 1.9.3-p327 that bring in garbage collection from the Ruby trunk, as well as some boot and runtime performance enhancements. Applying these patches is as simple as recompiling your local installation of Ruby. I'm using rbenv both on my i7 Macbook Air at home, and my i5 iMac in the office.
Check out this gist, which outlines all of the things you'll need to install these new patches. For me (using rbenv) it was as easy as pooping your pants:
curl https://raw.github.com/gist/1688857/rbenv.sh | sh ; rbenv global 1.9.3-p327-perf
Please kids, do not just copy-paste the above command. Inspect what it's doing first. Read the source, etc.. the last thing you want is to run some shell command from a remote website that deletes your entire home directory. I'd weep for days if I lost all of the My Little Pony episiodes in my ~/Movies folder.
To confirm we're running this new version:
michael at Achilles in ~
○ rbenv version
1.9.3-p327-perf (set by /Users/michael/.rbenv/version)
At least in my particular scenario, gems are dependent on the ruby version you are using. This makes perfect sense, so do not complain. Instead, simply re-install the gems you require. If you're working on a rails project, this too is a piece of cake.
gem install bundler
bundle
Done. I'm almost ready to run the benchmarks again.
The final adjustment that I made was following the advice of setting some environment variables to manually configure the behavior of Ruby's garbage collector. Here are the configuration options that are being touted. I have not actuall confirmed these values or even researched their purpose, I am simply trusting the community here:
export RUBY_GC_MALLOC_LIMIT=60000000
export RUBY_FREE_MIN=200000
Note that the linked gist contains most of this information, as well as further explanation on what this stuff does.
I placed these in my ~/.zshrc file and then source'd it to ensure that those environment variables were active. A simple echo $RUBY_HEAP_MIN_SLOTS will let you test that they exist.
Re-running our timed command yields the following results:
% time rails r 'puts 1'
1
rails r 'puts 1' 1.41s user 0.38s system 99% cpu 1.801 total
Boom! We went from approximately 3 seconds to less than two. The test completed in roughly 60% of the time, for a 40% increase in performance in this scenario.
I also have numbers for the 10-second Ask Herzl I benchmarked on the i5 iMac in the office after these identical adjustments:
% time rails r "puts 1"
Connecting to database specified by database.yml
1
rails r "puts 1" 2.95s user 0.90s system 58% cpu 6.549 total
Again, we went from around 10 seconds to 6.55. That's a 35% increase in performance!
I am not sure what implications will come from this. Generally you have to sacrifice something else for more speed (like higher memory usage) … that being said, the garbage collection enhancements should actually reduce memory consumption. So far I am enjoying the speed enhancements and will see how things perform! Now i'll need to do this on the server-side.
At some point I will be researching, detailing, and implementing additional Rails enhancements for lightweight REST/API configurations. Right now there are quite a few components that I do not need to be loading (session management for one).
If you enjoyed this post and would like to stay in the loop on others, please follow me on twitter!