Frank DENIS random thoughts.

Playing with Ruby 1.8, Ruby 1.9 and PHP

Today, I wanted to give a try to the latest Ruby 1.9 snapshot.

After disabling the set_thread_priority() call, it compiles and installs fine on OpenBSD. My test host is an Athlon 64 3400, running OpenBSD-current/amd64.

Before all, I wanted to benchmark it against Ruby 1.8.

Here’s a simple and stupid test script I wrote, just to have something that iterates over arrays, calls methods, use a class-scoped counter, and does common tests:

class String
  @@counter = 0

  def testfunc2
    array = self.split
    str = ""
    array.each do |word|
      str << word unless word.empty? or @@counter < 0
      @@counter += 1
    end
  end

  def testfunc!
    self << "abc "
    testfunc2.join("-")
  end
end

str = "initial string"
5000.times { str.testfunc! }

Very simple. It takes a string, it adds “abc “ to that string, it transforms it into an array of words, it iterates over every word and add each word to a new string with two useless tests by the way, it increments a class-wide counter, it returns the array of words, then all these words are joined by a dash. That happens 5000 times.

Here we go for the bench:

  • Ruby 1.8: 0m23.06s
  • Ruby 1.9: 0m11.65s

That’s pretty cool. Ruby 1.9 is more than twice as fast as Ruby 1.8 here!

Out of curiosity, I wanted to translate that simple example to PHP in order to see how it would compare. Unfortunately, adding methods to strings is something PHP is unable to do. PHP doesn’t let you extend strings, numerics, nor functions. So in order to do something similar to the previous test scripts, we have to reinvent the wheel, we have to invent a “String” class. Woah. And we can’t even use that class as a string, because unlike any object-oriented language from the past 20 years, PHP is not even able to overload operators. It’s why we have to invent a method (“set_value”) just to set the content of the string. Ok, here we go for the PHP version of the above script :

class String {
    var $str;
    protected static $counter = 0;
    
    public function set_value($str) {
        $this->str = $str;
    }
    
    public function __construct($str) {
        $this->set_value($str);
    }
    
    public function __toString() {
        return $this->str;
    }

    public function testfunc2() {
        $array = split(' ', $this);
        $str = "";
        foreach ($array as $word) {
            if (!(empty($word) || self::$counter < 0)) {
                $str .= $word;
            }
            self::$counter++;
        }
        return $array;
    }
    
    public function testfunc() {
        $this->set_value($this . "abc ");
        implode($this->testfunc2(), "-");
    }
}

$str = new String("initial string");
$i = 5000;
do {
    $str->testfunc();
} while (--$i !== 0);

All those “$this->” and “self::” are boring and useless, they don’t bring anything but ugly source code. PHP loves to annoy programmers by forcing them to write symbols like “$”, “_”, “->” and “::” everywhere. You have to write them over and over again, for everything you need in the current object, or you will get that wonderful error: “syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM”.

Okay, let’s benchmark the PHP script:

  • Ruby 1.8: 0m23.06s
  • Ruby 1.9: 0m11.65s
  • PHP 5.2.3: 1m36.46s

Yes, that’s one minute and 36 seconds. You got the codes, try them yourself. The PHP script is not only ugly, it’s also dog slow.

Please stop calling PHP a serious object-oriented language and please stop benchmarking languages over a function that computes prime numbers.