Hatena::ブログ(Diary)

Watsonのメモ RSSフィード

2011-07-03

MacRubyでCocoa APIのベンチマークをとってみた

今日は松江Ruby会議03があり、関係者のみなさま、ご苦労様でした。

MacRuby では Cocoa API と Ruby メソッドを使うことができます。ファイルを読み込む処理という単純な処理も、Cocoa API と Ruby メソッドを使って書くことができます。どの API を使うのがベストなのかベンチマーク計測してみました。

ファイルの読み込み

以下のようなベンチマークスクリプトを書きました。

framework 'Foundation'
require 'benchmark'

File.open("/tmp/bm_read.txt", "w") {|f|
  str = "x" * 10_000_000
  f.write str
}

Benchmark.bm(18) do |x|
  error = Pointer.new(:object)

  x.report "NSString" do
    10.times do
      str = NSString.stringWithContentsOfFile("/tmp/bm_read.txt",
                                              encoding:NSUTF8StringEncoding,
                                              error:error)
    end
  end

  x.report "NSString non-enc" do
    10.times do
      str = NSString.stringWithContentsOfFile("/tmp/bm_read.txt")
    end
  end


  x.report "NSMutableString" do
    10.times do
      str = NSMutableString.stringWithContentsOfFile("/tmp/bm_read.txt",
                                                     encoding:NSUTF8StringEncoding,
                                                     error:error)
    end
  end

  x.report "NSData" do
    10.times do
      data = NSData.dataWithContentsOfFile("/tmp/bm_read.txt")
      str  = String.new(data)
    end
  end

  x.report "IO.read" do
    10.times do
      io = File.open("/tmp/bm_read.txt")
      str = io.read
      io.close
    end
  end
end

結果は、

                        user     system      total        real
NSString            0.130000   0.070000   0.200000 (  0.167356)
NSString non-enc    0.270000   0.130000   0.400000 (  0.309619)
NSMutableString     0.180000   0.110000   0.290000 (  0.190521)
NSData              0.260000   0.160000   0.420000 (  0.236821)
IO.read             0.450000   0.190000   0.640000 (  0.333575)

NSString:stringWithContentsOfFile:encoding:error: が最速でファイルを読み込むことができました。

HTTPアクセス

HTTPを使ったデータ読み込みのベンチマークスクリプトを以下のように書きました。

require 'benchmark'
require 'open-uri'

URL = 'http://www.google.com/search?q=macruby'

Benchmark.bm(18) do |x|
  error = Pointer.new(:object)
  nsurl = NSURL.URLWithString(URL)

  x.report "NSString" do
    str = NSString.stringWithContentsOfURL(nsurl,
                                           encoding:NSUTF8StringEncoding,
                                           error:error)
  end

  x.report "NSString non-enc" do
    str = NSString.stringWithContentsOfURL(nsurl)
  end

  x.report "NSData" do
    data = NSData.dataWithContentsOfURL(nsurl)
    str  = String.new(data)
  end

  x.report "open-uri" do
    open(URL) {|f|
      str = f.read
    }
  end
end

結果は、

                        user     system      total        real
NSData              0.050000   0.010000   0.060000 (  0.202860)
NSString            0.010000   0.000000   0.010000 (  0.103459)
NSString non-enc    0.010000   0.010000   0.020000 (  0.094899)
open-uri            0.900000   0.010000   0.910000 (  0.857363)

今度は NSString:stringWithContentsOfURL: が最も速い結果となりました。Cocoa API も読み込むデータに合わせて使い分けたほうが良いみたいですね。

今回は Cocoa API のベンチマーク計測をしてみました。MacRuby を使うと簡単に API 単位でベンチマークを計測できます。また、Objective-CライブラリのテストにMacRubyを使うで書いた手順でライブラリを作れば、自作Objective-Cライブラリのベンチマーク計測も簡単に行うことができます。

普段 Objective-C でアプリケーションを作成している方でも、アプリケーションを最適化する際に役に立つのではないでしょうか(^o^)