メソッドの呼び出し方

PHPでは、static宣言なしでもメソッドのstatic呼び出しができてしまう。
で、どっちが速いの?という話。
メモリの使用量も比べてみたかったけど、速さのみ。

<?php
require_once 'Benchmark/Timer.php';

class MyTest {
  public function myMethod() {
    return;
  }
  public static function staticMethod() {
    return;
  }
}

$max = 100000;
$timer = new Benchmark_Timer();
$t = new MyTest();

$timer->start();

for($i = 0; $i < $max; $i++) {
  MyTest::staticMethod();
}
$timer->setMarker('static');

for($i = 0; $i < $max; $i++) {
  MyTest::myMethod();
}
$timer->setMarker('static2');

for($i = 0; $i < $max; $i++) {
	$t->myMethod();
}
$timer->setMarker('instance');

$timer->stop();
$timer->display();

/*
------------------------------------------------------
marker    time index            ex time         perct   
------------------------------------------------------
Start     1293934691.81032700   -                0.00%
------------------------------------------------------
static    1293934691.85720200   0.046875        21.74%
------------------------------------------------------
static2   1293934691.99593900   0.138737        64.35%
------------------------------------------------------
instance  1293934692.02592700   0.029988        13.91%
------------------------------------------------------
Stop      1293934692.02593700   0.000010         0.00%
------------------------------------------------------
total     -                     0.215610       100.00%
------------------------------------------------------
*/
$ php --version
PHP 5.3.3 (cli) (built: Aug 22 2010 19:41:55)

static宣言なしのメソッドをstaticに呼ぶのは遅いってことかしら。

ちなみにrubyだとこうなった。
static methodは存在しないので、class method。このへんはうろ覚えなので、ちょっと自信ない・・・

require 'benchmark'

class MyTest
  def myMethod
    1 + 2
  end

  def self.classMethod
    1 + 2
  end
end

module MyModule
  def moduleMethod
    1 + 2
  end
end

module MyModule2
  def moduleClassMethod
    1 + 2
  end
end

max = 100000;

Benchmark.bmbm(10) do |x|
  t = MyTest.new
  x.report("instance: ") {
    max.times do
      t.myMethod
    end
  }

  x.report("class   : ") {
    max.times do
      MyTest::classMethod
    end
  }

  MyTest.class_eval {
    include MyModule
  }
  t = MyTest.new
  x.report("module : ") {
    max.times do
      t.moduleMethod
    end
  }

  MyTest.extend MyModule2
  x.report("module class : ") {
    max.times do
      MyTest::moduleClassMethod
    end
  }
end
Rehearsal ---------------------------------------------------
instance:         0.040000   0.000000   0.040000 (  0.043314)
class   :         0.050000   0.000000   0.050000 (  0.049375)
module :          0.040000   0.000000   0.040000 (  0.042887)
module class :    0.050000   0.000000   0.050000 (  0.045320)
------------------------------------------ total: 0.180000sec

                      user     system      total        real
instance:         0.040000   0.000000   0.040000 (  0.042020)
class   :         0.040000   0.000000   0.040000 (  0.046069)
module :          0.040000   0.000000   0.040000 (  0.041350)
module class :    0.040000   0.000000   0.040000 (  0.045474)
$ ruby --version
ruby 1.8.7 (2010-08-16 patchlevel 302) [i686-darwin10]