I have started using Octopress last year for my other blog (in Romanian) tastatura.info.
Octopress is advertised as “a blogging framework for hackers”. As a hacker one “should be comfortable running shell commands and familiar with the basics of Git”. But it all comes down to ruby.
If you’re a Windows hacker what do you do? My first idea was to install Cygwin.
For tastatura.info I’ve used Cygwin to run Octopress. I had a laptop with an Intel Core i7 CPU, didn’t notice any slowdowns.
By the time I’ve moved this blog to Octopress I didn’t have access to that Intel Core i7 powered laptop, but instead I had an Intel Core 2 Duo powered laptop. Then I’ve noticed that Octopress was rather slow on Cygwin.
That’s when I’ve started looking for alternatives to Cygwin.
The other options for running Ruby on Windows are:
- RubyInstaller - The easy way to install Ruby on Windows
- Running Ruby on Linux in a virtual machine
- Compiling Ruby by myself
Octopress requires a few ruby libraries (gems) which require a native C/C++ compiler.
RubyInstaller provides a development kit, which is a “MSYS/MinGW based toolkit than enables you to build many of the native C/C++ extensions available for Ruby”.
Since Visual Studio 2013 Professional has been offered freely as the Community Edition, I decided to use Visual C++ to compile Ruby.
In my experience Visual C++ generates faster and smaller binaries than MinGW (GCC for Windows).
Before starting to compile Ruby one needs to compile some dependencies:
- OpenSSL - requires Perl for building
- Zlib - has a CMake configuration, very nice!
- libffi - the worst of the lot, very unfriendly on Windows
Ruby can be compiled with Visual C++. Ruby provides a NMake makefile script. Building with NMake can be very slow because it runs only on a CPU core. I’ve tried to use Jom - the parallel NMake clone, unfortunately the Ruby makefile is not parse-able by Jom, it was complaining about some recursive declarations.
I haven’t mentioned the Ruby version I was trying to compile and when I’ve done this exercise. I’ve compiled ruby 2.0.0p598 at the beginning of March, I’ve chosen ruby 2.0 because at that time the newer version was crashing at runtime. Also that’s the same ruby version that Cygwin was providing back then.
Ruby 2.0.0.p598 doesn’t compile successfully out of the box with Visual C++ 2013 64bit.
The following patch does the trick:
Compiling Ruby is not enough, one needs to compile the required gems for Octopress.
Bundler will try to compile the missing gems when you issue bundle install
. This is
why one needs to run all these commands from VS2013 x64 Native Tools Command Prompt
.
The following gems required patches:
- hitimes-1.2.2 (updated gem, patch)
- rdiscount-2.1.8 (updated gem, patch)
- wdm-0.1.0 (updated gem, patch)
Now I had a running Octopress setup. But after a quick benchmark I’ve noticed that the RubyInstaller had a faster binary build with MinGW 4.7.2 x64
Then I decided to do a Profile Guided Optimization (PGO) build. This required a few modifications
for Makefile.sub: OPTFLAGS = -O2sy- -GL
and LDFLAGS = -incremental:no -debug -opt:ref -opt:icf -force:multiple -LTCG:$(LTCG)
.
I had LTCG
as a shell variable because one needs to compile the binaries twice and editing Makefile.sub
would trigger a rebuild. The value for $(LTCG)
is set first as /LTCG:PGINSTRUMENT
and after instrumentation set as /LTCG:PGOPTIMIZE
or /LTCG:PGUPDATE
.
I also had to hack mkexports.rb
to export all final symbols instead of progressively gather them from
the shared objects.
At the end I had an PGO optimized build for Octopress which was faster than RubyInstaller
And now for some numbers. I have tested RubyInstaller x64, ruby 2.0 installed on a Kubuntu 14.10 x86 on Virtual Box and VMware Player, ruby 2.0 installed on Kubuntu 14.10 x64 on the same machine, Cygwin x64. The Core 2 Duo laptop was not able to run x64 virtual machines, that’s due to a hardware limitation.
I used MSys Git (because it had bash and no ruby) to run this script for tastatura.info:
This means that the times below are for ten rake generate
commands:
Ruby | Time | Time with antivirus enabled |
---|---|---|
ruby 2.0.0p598 [x64-mingw32] RubyInstaller |
2m7.343s | 2m32.256s |
ruby 2.0.0p598 [x64-mswin64_120] Visual C++ 2013 |
2m17.998s | 2m43.675s |
ruby 2.0.0p598 [x64-mswin64_120] Visual C++ 2013 PGO Optimized |
2m2.117s | 2m27.561s |
ruby 2.0.0p598 [x86_64-cygwin] Cygwin |
7m12.776s | 7m35.724s |
ruby 2.0.0p457 [i386-linux-gnu] VMware Player 7.1.0 |
1m31.512s | - |
ruby 2.0.0p457 [i386-linux-gnu] VirtualBox 4.3.24 (ICH9, I/O APIC Enabled) |
2m15.348s | - |
ruby 2.0.0p457 [i386-linux-gnu] VirtualBox 4.3.24 (PIIX3, I/O APIC Disabled) |
2m32.534s | - |
ruby 2.0.0p457 [x86_64-linux-gnu] Kubuntu 14.10 |
1m9.711s | - |
From these numbers we can see that running ruby on Cygwin is a bad idea. Running ruby in a virtual machine with VMware Player was the fastest option on Windows. Running ruby on Linux natively produced the fastest results.
The antivirus penalty seems to be similar for all Windows options.
tastatura.info had like ten articles, therefore I decided to test my old blog entries imported into Octopress. My old blog had like one hundred articles.
Ruby | Time | Time with antivirus enabled |
---|---|---|
ruby 2.0.0p598 [x64-mingw32] RubyInstaller |
5m52.670s | 6m19.283s |
ruby 2.0.0p598 [x64-mswin64_120] Visual C++ 2013 |
6m50.686s | 7m18.096s |
ruby 2.0.0p598 [x64-mswin64_120] Visual C++ 2013 PGO Optimized |
5m23.810s | 5m48.801s |
ruby 2.0.0p598 [x86_64-cygwin] Cygwin |
11m14.888s | 11m42.282s |
ruby 2.0.0p457 [i386-linux-gnu] VMware Player 7.1.0 |
6m10.477s | - |
ruby 2.0.0p457 [i386-linux-gnu] VirtualBox 4.3.24 (ICH9, I/O APIC Enabled) |
7m29.291s | - |
ruby 2.0.0p457 [i386-linux-gnu] VirtualBox 4.3.24 (PIIX3, I/O APIC Disabled) |
7m32.479s | - |
ruby 2.0.0p457 [x86_64-linux-gnu] Kubuntu 14.10 |
4m58.092s | - |
The results are a bit different. Cygwin is still slow, but now the fastest option on Windows is no longer VMware Player but instead the PGO Visual C++ build. Ruby on Linux is still the fastest option for that Core 2 Duo laptop. The difference from Linux and Windows PGO Visual C++ is not that dramatic.
Below you have the Visual C++ 2013 ruby 2.0.0p598 x64 binaries:
In order to use them you need to install Visual Studio Community Edition.
Install the patched ruby gems gem install --local path_to_gem/filename.gem
from the VS2013 x64 Native Tools Command Prompt window.
After a successful bundle install
one just needs to run Ruby-x64-pgo\setrbvars.cmd
from a
command prompt and then the usual rake new_post[""]
, rake generate
, or rake preview
commands!
If you use Octopress on Windows, give this build a try