I had a really bad experience of the Ruby standard library today. I sat down with a colleague to look at the performance of a small piece of code that happened to be in a hot spot of our code base. We set up a simple benchmark, saw that it was less than ideal performance, reasoned a bit about the code and decided that perhaps it would be better to replace the use of
SortedSet with just
#sort! for this particular case. So just to be sure we ran
perftools.rb to see what was going on. This is what we saw:
#sort! wouldn’t be such a good idea after all. And what is
SortedSet doing? Why is is even calling
#sort!? How is it a sorted set if it needs to call
Turns out that
The first the class does is to try to load
rbtree. Yes, the standard library class
SortedSet is implemented in terms of the gem
rbtree. If it can’t load
rbtree it creates (via
module_eval and a huge string containing the code, of course) a completely retarded implementation instead.
What. The. Fuck.
The Ruby standard library has gotten some (rightful!) flak over the years, but for me this really takes the biscuit. The Ruby standard library is a disgrace. The Ruby community should have thrown it out a long time ago. It’s full of awful code — some of the worst Ruby code I have ever seen is in the standard library. Many of the APIs are horrible, and much of it was written almost as to be as slow as possible.
I think it puts the Ruby community in a bad light. We should be ashamed of it.
If you’ve somehow escaped noticing the issues with the standard library, here’s a smalll gallery of horrors.
An API so byzantine that it makes SOAP look simple. Have you ever written code that used
Net::HTTP without looking at the documentation first?
That someone wrote
open-uri to hide the ugliness for most use cases is one of the few redeeming qualities of the standard library.
There’s tons of good HTTP libraries available as gems, thankfully.
Until recently the code that parsed query strings had an exponential backtrack bug caused by this regex
now it’s changed to
so that’s good, I guess.
Don’t get me started on
Date. It’s been updated in 1.9.3 it seems, but prior to that the performance was just atrocious, and the code was even worse.
date/format.rb was completely indecipherable before, but now it’s been
ported one-way encrypted to C.
The bottom of the barrel
Then there’s the rest. The things that have ended up in the standard library for historical reasons. For some of it I guess it felt like the right thing to include at the time, but other things are just weird. Why is there a prime number finder in the standard library? Why two option parsing libraries? Why
There’s been suggestions of moving it out of the distribution and into a default gem or gems. Hopefully we’ll see that in Ruby 2.0. It wouldn’t make the code any better but it would at least be a small step in the right direction.
I think it’s a pity that good libraries like Rake were moved in to the standard library, it feels like the opposite of what we want. The slow release cycle makes it completely pointless trying to contribute to making it better. It’s so much easier to write a gem, or send a pull request to an existing gem, push it to RubyGems. The standard library is where gems go to die.
To contribute, and so that you can’t say I’m not doing my part to making things better, I’ve created a gem called Sanity that does one very simple thing: it removes the standard library from the load path. Just
require "sanity" and you will no longer be exposed to the insanity of
URI and friends.