'The Rails 4 Way' is the latest edition of the most comprehensive, authoritative guide to delivering production-quality code with Rails 4.
About half a year ago Vitaly posted a post about how simple it is today to use ruby patches bundled with rvm installation to dramatically reduce big rails app loading times and make your dev environment a much happier place.
Since then Ruby advanced with new patchlevels and there are new patches to use, so let's go over this once again.
First, we start with upgrading the rvm to latest and hopefully greatest
rvm get head
Since Vitaly wrote his post it seems that the railsexpress patch superseded the falcon one. At least that what i got from browsing over the patches repository.
So, next step is to compile our Ruby version with railsexpress patchset applied
rvm install 1.9.3-p392-railsexpress --patch railsexpress
Ok, now for some trivial benchmarking to ensure we made things better and not the other way around. Now, note that the say in the interwebs goes that the bigger your application and amount of gems it has to load the more happy you will be. Also, the usual disclaimer about those performance things, YMMV.
I took a random application from my dev folder. It loads 147 gems. Let's check out some numbers
✗ rvm use 1.9.3 Using /usr/local/rvm/gems/ruby-1.9.3-p392 ✗ time rails runner "puts :OK" OK rails runner "puts :OK" 16.28s user 1.70s system 98% cpu 18.185 total ✗ rvm use 1.9.3-p392-railsexpress Using /usr/local/rvm/gems/ruby-1.9.3-p392-railsexpress ✗ time rails runner "puts :OK" OK rails runner "puts :OK" 8.56s user 1.22s system 99% cpu 9.820 total
Just to make a comparison to the previous blog post, here are the numbers for the same application with ruby 1.9.3-p327 with falcon patches set:
✗ rvm use 1.9.3-p327-falcon Using /usr/local/rvm/gems/ruby-1.9.3-p327-falcon ✗ time rails runner "puts :OK" rails runner "puts :OK" 9.89s user 1.34s system 98% cpu 11.374 total
So, comparing to falcon patches it's not that big of an improvement, but still, another 1.5 seconds win.
And yes, i know that both before and after times are slow. But still, i see a nice around 50% time save on any environment loading. And what i really like is that this improvement demanded the whole 7 minutes of my time.
I knew that there are various Ruby patches available but I've never tried them as I didn't want to waste time for something that I thought I don't really need.
Then I found out that rvm comes bundled with patches ready to be applied, so I'm just a simple command line away from having a patched Ruby. Don't know how I missed that before.
One particular patch that worth trying is falcon. It improves startup time of big Ruby applications. And the bigger your Gemfile is the bigger the improvement.
Try it right now for yourself. It will only take a couple of minutes.
First upgrade rvm to make sure you have the latest
rvm get head
Then the actual Ruby build
rvm install 1.9.3 --patch falcon -n falcon
Note that this command can fail with the following error: Patch 'falcon' not found. The reason is that falcon patch is not yet supported on the latest Ruby patch level, in which case you will need to specify older patch level to make it work.
Find out what patchlevels have falcon support
✗ ls $rvm_path/patches/ruby/1.9.3/*/*falcon* | sort /usr/local/rvm/patches/ruby/1.9.3/p0/falcon.patch /usr/local/rvm/patches/ruby/1.9.3/p125/falcon.patch /usr/local/rvm/patches/ruby/1.9.3/p194/falcon.diff /usr/local/rvm/patches/ruby/1.9.3/p286/falcon.diff
So latest patch level with falcon support is 286 at the time of this writing.
Install specific patch level with falcon support
rvm install ruby-1.9.3-p286 --patch falcon -n falcon
Congratulations, you now have a patched Ruby installed.
Lets test how much improvement it is. The following is for one of my current projects with about 50 gems:
✗ rvm use default Using /usr/local/rvm/gems/ruby-1.9.3-p194 ✗ time bin/rails runner "puts :OK" OK bin/rails runner "puts :OK" 6.47s user 0.60s system 99% cpu 7.106 total ✗ rvm use ruby-1.9.3-p286-falcon Using /usr/local/rvm/gems/ruby-1.9.3-p286-falcon ✗ time bin/rails runner "puts :OK" OK bin/rails runner "puts :OK" 2.79s user 0.52s system 98% cpu 3.354 total
Nice! Startup time decreased from 3.354 to 1.106 seconds. More then twice faster.
I'm going to use this Ruby by default now
rvm use ruby-1.9.3-p286-falcon --default
And while we are on the "lets improve rails startup times" subject, lets do one more change. Add the following to your shell startup file. i.e. ~/.bashrc or ~/.zshrc
export RUBY_HEAP_MIN_SLOTS=1000000 export RUBY_HEAP_FREE_MIN=500000 export RUBY_HEAP_SLOTS_INCREMENT=1000000 export RUBY_HEAP_SLOTS_GROWTH_FACTOR=1 export RUBY_GC_MALLOC_LIMIT=100000000
This will tune Ruby GC settings to be better suited for running big apps (as it seems to be tuned for small Ruby scripts by default).
Lets see how much improvement that is
✗ time bin/rails runner "puts :OK" OK bin/rails runner "puts :OK" 2.27s user 0.58s system 98% cpu 2.890 total
Total improvement from 7.106 to 2.890 is almost 60%.
Now, stop fiddling with the environment and go back to creating something great! :)
I recently switched to ruby 1.9.3 as my deafult ruby verison, and suddenly some of my scripts started to fail in funny ways.
One of the latest ones was the script that was supposed to change 'updated' timestamp in a YAML formatted file. Instead of the current date it started to spit out binary strings.
The problem is quite complext but the fix is simple...
First lets see what happens:
In ruby 1.9.2p320:
> require 'yaml' => true > Time.now.to_s.to_yaml => "--- 2012-09-03 22:20:15 +0300\n"
In ruby 1.9.3p194:
> require 'yaml' => true > Time.now.to_s.to_yaml => "--- !binary |-\n MjAxMi0wOS0wMyAyMjoyMDozMCArMDMwMA==\n"
Why did that happen?
This happens because Time.now.to_s returns a non-ascii string
> Time.now.to_s.encoding => #<Encoding:ASCII-8BIT>
To remind you, UTF-8 is backwards compatible with the standard 7bit ASCII, as the ASCII is just the subset of UTF8 where the 8th bit is 0;
So to output an 8bit ASCII in UTF-8 a conversion might be required (for example when time format contains regional characters from the upper part of the 8bit ASCII).
It is the same in 1.9.2 but apparently YAML over there knows how to handle it in the case when the string doesn't actually contain any 8bit characters.
In 1.9.3, instead of performing conversions YAML seems to just opting for the 'lets treat it as a binary' handling.
The problem of encodings is complex and "hairy", so we wont go into details here, but in the case when you just need a quick fix like I did you do this:
> YAML::ENGINE.yamler='syck' => "syck" > Time.now.to_s.to_yaml => "--- 2012-09-03 22:24:22 +0300\n"
And the problem solved.
Given that module Foo is defined elsewhere what is the difference between the following 2 code snippets?
class Foo::Bar ... end
module Foo class Bar ... end end
It is actually quite simple. The following code:
# foo.rb module Foo BAR = 123 end module Foo class A puts BAR end end class Foo::B puts BAR end
123 foo.rb:13:in `': uninitialized constant Foo::B::BAR (NameError) from foo.rb:12:in `
Simply put, while A has access to the insides of the module's Foo namespace, class B is defined outside of this namespace, only the result of the definition is put as a constant inside Foo.
I most frequently stumble on this when I want to define some common constants in the parent module, just like in the example above. Given that and the fact that the 2nd form doesn't actually require the module to be defined, the 2nd form is probably better and is a safer bet in most cases.
I was working on tests for blender when I came upon a need to mock or stub a back-tick operator e.g.:
Apparently this is just a shortcut for calling Kernel method :`.
I just recently reinstalled my MacBook Pro, this time with Snow Leopard.
So I'm again going through various installation problems I already forgot about from few years back when I installed Leopard.
Anyway, just had to hunt down a problem with mysql gem installation on Snow Leopard.
I've just read "Do You Believe In Magic?" and the following quote resonated particularly well:
"It's not magic. There is no magic involved. It's just, if you never learnt Lisp, then you never learned to program, and Ruby's power is exposing a deficiency in your skills."
Mephisto commenting system is... how do i put it ... outdated :)
And we wanted something more engaging for our blog. Looking around the web we found that Disqus was used all over the place, so we decided to integrate it into our blog instead of the native comments system.
RRDtool is the OpenSource industry standard, high performance data logging and graphing system for time series data. Use it to write your custom monitoring shell scripts or create whole applications using its Perl, Python, Ruby, TCL or PHP bindings.
Let's run it with Ruby on Leopard.
sudo port install rrdtool
Default ports installation comes without ruby bindings.
Thanks a lot to Amit Hurvitz for providing a file of Virtual Disk Image (VDI) of VirtualBox, containing an up and running JRuby on Rails on Glassfish with Mysql. Image also contains some examples (actually solutions to the code camp exercises), all running on top of an OpenSolaris guest OS (can be run on many host systems).
Grab the image ~1.5GB archive.
Grab the exercises ~9.7MB archive.
We participated in JRuby on Rails with GlassFish Code Camp hosted by Sun Microsystems Inc. I was speaking about the framework in general trying to infect Java developers with Ruby On Rails. Slides are available.
I was the last person in our company working with ERB to render templates. While all the rest switched to HAML. At the beginning it was quite hard for me to read HAML comparing to ERB. HAML looked for me like some completely alien thing with weird percent marks all over the place and the significant whitespace never did it for me. On the other hand ERB felt like warm home after years we spent together.
Until I did the switch.
Recently we looked for video transcoding/hosting solution to use in one of our client's projects.
Using amazon has many advantages. no contracts, pay as you go, easy and fast scaling in case your site explodes :)
Unfortunately the image that is refered in the Getting Started (ami-05d7336c) is not safe for production - it has openssh version with a serious security bug, but don't worry, we will explain how to fix it.
We really like Debian and we usually use the current "stable" distribution for our production servers.
It all works great with one little problem: if you need very current soft it is probably not in the 'stable' yet.
The current Debian stable ("etch") includes rubygems 0.9.0-5 which is way too old.
We needed to upgrade to at least 1.2.
On one of our projects we needed to do some caching for an action with an expensive db query. Fragment caching took care of the rendering but we needed a way to skip the db if we have a cache hit. And checking for an existence of the fragment file in the controller just didn’t seem right.