Cайт веб-разработчика, программиста Ruby on Rails ESV Corp. Екатеринбург, Москва, Санкт-Петербург, Первоуральск

Сравнение производительности Ruby 2 и PHP 5.4

Более сложный тест производительности (mandelbrot, если верить источнику), решил сравнить уже конкретно Ruby 2 (ruby 2.0.0p0 (2013-02-24 revision 39474) [x86_64-linux]) и PHP 5.4 (PHP 5.4.4-14 (cli) (built: Mar  4 2013 14:08:43), Zend Engine v2.4.0).

 

PHP:

$count = array( 320, 320 * 2, 320 * 4 );

$i = 0;

while (true) {

	if ($i > 2) {
	  break;
	}

	$size = $count[$i];

	$i += 1;

	print "$i : $size\n";

	$time = microtime(true);

	$byte_acc = 0;
	$bit_num = 0;

	$sum = 0;

	$y = 0;

	while ($y < $size) {

		$ci = (2.0 * $y / $size) - 1.0;

		$x = 0;

		while ($x < $size) {

			$zrzr = $zr = 0.0;
			$zizi = $zi = 0.0;
			$cr = (2.0 * $x / $size) - 1.5;

			$escape = 0b1;

			$z = 0;

			while ($z < 50) {

				$tr = $zrzr - $zizi + $cr;
				$ti = 2.0 * $zr * $zi + $ci;
				$zr = $tr;
				$zi = $ti;

				// preserve recalculation
				$zrzr = $zr * $zr;
				$zizi = $zi * $zi;

				if ($zrzr + $zizi > 4.0) {
				  $escape = 0b0;
				  break;
				}

				$z += 1;

			}

			$byte_acc = ($byte_acc << 1) | $escape;
			$bit_num += 1;

			// Code is very similar for these cases, 
      // but using separate blocks
			// ensures we skip the shifting when it's unnecessary,
      // which is most cases.
			if ($bit_num == 8) {
			  $sum += $bit_num + $byte_acc;
			  $byte_acc = 0;
			  $bit_num = 0;
			} elseif ($x == $size - 1) {
			  $byte_acc <<= (8 - $bit_num);
			  $sum += $bit_num + $byte_acc;
			  $byte_acc = 0;
			  $bit_num = 0;
			}

			$x += 1;
		}

	  $y += 1;

	}

	print "$sum\n";
	print (microtime(true) - $time) . "\n";

}

Результаты:

1 : 320
1394601
0.96925115585327
2 : 640
5586324
3.8755822181702
3 : 1280
22350292
15.504486083984

 

Ruby:

require "benchmark"

Benchmark.bm do | make |

  count = [ 320, 320 * 2, 320 * 4 ]

  i = 0

  while true

    if i > 2
      break
    end

    size = count[i]

    i += 1

    make.report do

      puts "#{i} : #{size}"

      byte_acc = 0
      bit_num = 0

      sum = 0

      y = 0

      while y < size

        ci = (2.0 * y / size) - 1.0

        x = 0

        while x < size

          zrzr = zr = 0.0
          zizi = zi = 0.0
          cr = (2.0 * x / size) - 1.5

          escape = 0b1

          z = 0

          while z < 50

            tr = zrzr - zizi + cr
            ti = 2.0 * zr * zi + ci
            zr = tr
            zi = ti

            # preserve recalculation
            zrzr = zr * zr
            zizi = zi * zi

            if zrzr + zizi > 4.0
              escape = 0b0
              break
            end

            z += 1

          end

          byte_acc = (byte_acc << 1) | escape
          bit_num += 1

          # Code is very similar for these cases,
          # but using separate blocks
          # ensures we skip the shifting when it's unnecessary,
          # which is most cases.
          if (bit_num == 8)
            sum += bit_num + byte_acc
            byte_acc = 0
            bit_num = 0
          elsif (x == size - 1)
            byte_acc <<= (8 - bit_num)
            sum += bit_num + byte_acc
            byte_acc = 0
            bit_num = 0
          end

          x += 1

        end

        y += 1

      end

      puts "#{sum}"

    end

  end

end

Результаты:

 1 : 320
1394601
  0.800000   0.000000   0.800000 (  0.806134)
 2 : 640
5586324
  3.200000   0.010000   3.210000 (  3.207576)
 3 : 1280
22350292
 12.770000   0.060000  12.830000 ( 12.835360)

 

Получается, что на этом тесте Ruby быстрее на ~20%, чем PHP.

На простейших тестах, в которых производится вызов функции или обращение к методу объекта, Ruby быстрее на ~50%, что фактически показывает, что PHP в 2 (!) раза медленнее Ruby.