dRubyのパフォーマンス測定

経緯

プロセス間通信でdRubyを使おうと思ったが、パフォーマンスが気になったので測定してみた。

コード

ベンチマークは自作の次のスクリプトを使う。 github.combenchmark_basic.rbを使用。

ベンチマークコードの抜粋:

n = ARGV.shift || '1_000_000'
n = n.to_i

def method_no_args
end

def method_default(a=:foo)
end

def method_a1(a)
end

def method_a2(a, b)
end

def method_a3(a, b, c)
end

def method_args(*args)
end

def method_keywords(options={})
end

def method_block
  yield
end

class RemoteObject
  def method_no_args
  end

  def method_default(a=:foo)
  end

  def method_a1(a)
  end

  def method_a2(a, b)
  end

  def method_a3(a, b, c)
  end

  def method_args(*args)
  end

  def method_keywords(options={})
  end

  def method_block
    yield
  end
end

druby_remote_uri = 'drbunix:' + File.expand_path(File.join(File.dirname($0), "druby_remote.#{$$}"))
druby_local_uri = 'drbunix:' + File.expand_path(File.join(File.dirname($0), "druby_local.#{$$}"))

pid = fork{
  DRb.start_service(druby_remote_uri, RemoteObject.new)
  DRb.thread.join
}

at_exit{
  Process.kill('TERM', pid)
}

DRb.start_service(druby_local_uri)
drb_remote_obj = DRbObject.new_with_uri(druby_remote_uri)

# wait to start remote server
begin
  drb_remote_obj.method_no_args
rescue DRb::DRbConnError
  sleep(0.1)
  retry
end

Benchmark.bm(45) do |x|
  x.report('method_no_args') {
    n.times do
      method_no_args
    end
  }
  x.report('method_default') {
    n.times do
      method_default
    end
  }
  x.report('method_a1') {
    n.times do
      method_a1(1)
    end
  }
  x.report('method_a2') {
    n.times do
      method_a2(1, 2)
    end
  }
  x.report('method_a3') {
    n.times do
      method_a3(1, 2, 3)
    end
  }
  x.report('method_args') {
    n.times do
      method_args(1, 2, 3)
    end
  }
  x.report('method_keywords') {
    n.times do
      method_keywords(foo: 1, bar: 2, baz: 3)
    end
  }
  x.report('method_block do end') {
    n.times do
      method_block do
      end
    end
  }
  x.report('method_block{}') {
    n.times do
      method_block{
      }
    end
  }
  x.report('[1/100] drb_remote_obj.method_no_args') {
    (n / 100).times do
      drb_remote_obj.method_no_args
    end
  }
  x.report('[1/100] drb_remote_obj.method_default') {
    (n / 100).times do
      drb_remote_obj.method_default
    end
  }
  x.report('[1/100] drb_remote_obj.method_a1') {
    (n / 100).times do
      drb_remote_obj.method_a1(1)
    end
  }
  x.report('[1/100] drb_remote_obj.method_a2') {
    (n / 100).times do
      drb_remote_obj.method_a2(1, 2)
    end
  }
  x.report('[1/100] drb_remote_obj.method_a3') {
    (n / 100).times do
      drb_remote_obj.method_a3(1, 2, 3)
    end
  }
  x.report('[1/100] drb_remote_obj.method_args') {
    (n / 100).times do
      drb_remote_obj.method_args(1, 2, 3)
    end
  }
  x.report('[1/100] drb_remote_obj.method_keywords') {
    (n / 100).times do
      drb_remote_obj.method_keywords(foo: 1, bar: 2, baz: 3)
    end
  }
  x.report('[1/100] drb_remote_obj.method_block do end') {
    (n / 100).times do
      drb_remote_obj.method_block do
      end
    end
  }
  x.report('[1/100] drb_remote_obj.method_block{}') {
    (n / 100).times do
      drb_remote_obj.method_block{
      }
    end
  }
end

測定

実行結果の抜粋:

1,000,000 times.
                                                    user     system      total        real
method_no_args                                  0.457672   0.000000   0.457672 (  0.457662)
method_default                                  0.627657   0.000000   0.627657 (  0.627657)
method_a1                                       0.475510   0.000004   0.475514 (  0.475568)
method_a2                                       0.481245   0.000000   0.481245 (  0.481259)
method_a3                                       0.494288   0.000000   0.494288 (  0.494388)
method_args                                     1.146560   0.000000   1.146560 (  1.146752)
method_keywords                                 2.559685   0.000000   2.559685 (  2.560266)
method_block do end                             0.670567   0.000000   0.670567 (  0.670818)
method_block{}                                  0.670467   0.000000   0.670467 (  0.670500)
[1/100] drb_remote_obj.method_no_args           1.482313   0.306498   1.788811 (  4.789675)
[1/100] drb_remote_obj.method_default           1.541902   0.272193   1.814095 (  4.933442)
[1/100] drb_remote_obj.method_a1                1.682313   0.262968   1.945281 (  5.310548)
[1/100] drb_remote_obj.method_a2                1.936925   0.170552   2.107477 (  5.754095)
[1/100] drb_remote_obj.method_a3                1.891366   0.351507   2.242873 (  6.103683)
[1/100] drb_remote_obj.method_args              2.018824   0.219010   2.237834 (  6.194996)
[1/100] drb_remote_obj.method_keywords          1.924781   0.241488   2.166269 (  5.759805)
[1/100] drb_remote_obj.method_block do end      6.226273   0.649228   6.875501 ( 12.205400)
[1/100] drb_remote_obj.method_block{}           6.274446   0.661823   6.936269 ( 12.281795)

Rubyの素のメソッド呼び出しが0.5μs~数μsに対して、dRubyのメソッド呼び出しは500μs~千μs (0.5ms~1ms)かかるようだ。

環境情報

パフォーマンス測定で使った環境は次の通り。

$ ruby -v
ruby 2.5.3p105 (2018-10-18 revision 65156) [armv7l-linux-eabihf]
$ uname -a
Linux gut 4.14.74-v7+ #1149 SMP Mon Oct 8 17:39:42 BST 2018 armv7l GNU/Linux
$ cat /proc/cpuinfo
processor       : 0
model name      : ARMv7 Processor rev 4 (v7l)
BogoMIPS        : 38.40
Features        : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part        : 0xd03
CPU revision    : 4

processor       : 1
model name      : ARMv7 Processor rev 4 (v7l)
BogoMIPS        : 38.40
Features        : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part        : 0xd03
CPU revision    : 4

processor       : 2
model name      : ARMv7 Processor rev 4 (v7l)
BogoMIPS        : 38.40
Features        : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part        : 0xd03
CPU revision    : 4

processor       : 3
model name      : ARMv7 Processor rev 4 (v7l)
BogoMIPS        : 38.40
Features        : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm crc32
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part        : 0xd03
CPU revision    : 4

Hardware        : BCM2835
Revision        : a020d3
Serial          : 00000000a40d8075