[Rubycocoa-devel 962] Re: defining missing methods

Back to archive index

Laurent Sansonetti lsans****@apple*****
Fri Jun 8 16:24:11 JST 2007


I committed a working experiment as r1821!

It automatically defines the method directly in C by generating Libffi  
closures.

$ cat bench.rb
require 'benchmark'
require 'osx/foundation'

def job
   ary = OSX::NSMutableArray.alloc.init
   str = OSX::NSString.stringWithString('foo')
   ary.addObject(str)
   num = OSX::NSNumber.numberWithInt(42)
   ary.addObject(num)
   count = ary.count
   ary.removeAllObjects
end

puts Benchmark.measure { 1000.times { job } }
puts Benchmark.measure { 10_000.times { job } }
puts Benchmark.measure { 100_000.times { job } }

*** Old RubyCocoa ***

$ ruby bench.rb
   0.170000   0.000000   0.170000 (  0.168513)
   1.640000   0.010000   1.650000 (  1.686002)
  16.450000   0.080000  16.530000 ( 16.764010)
$ ruby bench.rb
   0.170000   0.000000   0.170000 (  0.173943)
   1.640000   0.010000   1.650000 (  1.679036)
  16.510000   0.100000  16.610000 ( 16.931537)

*** New RubyCocoa ***

$ ruby bench.rb
   0.070000   0.000000   0.070000 (  0.066736)
   0.650000   0.000000   0.650000 (  0.656822)
   6.490000   0.040000   6.530000 (  6.598461)
$ ruby bench.rb
   0.070000   0.000000   0.070000 (  0.067404)
   0.650000   0.000000   0.650000 (  0.671378)
   6.520000   0.040000   6.560000 (  6.705908)

In average ~3 times faster!

All tests and samples are working on my environment. I will verify on  
other environments later.

If you find something wrong please tell me.

Laurent

On Jun 6, 2007, at 11:56 AM, Laurent Sansonetti wrote:

> After a quick investigation, it seems that #define_method is the
> culprit. It's really slow when used with Proc. Using a regular eval to
> add the method seems to be better.
>
> $ cat bench2.rb
> require 'benchmark'
> class Foo
>   def method_missing(*a); foo; end
>   def foo; end
> end
> Foo.class_eval { define_method(:foo2) { 0 } }
> Foo.class_eval("def foo3; end")
> n = 1_000_000
> Benchmark.bm(7) do |x|
>   o = Foo.new
>   x.report('method_missing') { n.times { o.missing } }
>   x.report('define_method') { n.times { o.foo2 } }
>   x.report('eval') { n.times { o.foo3 } }
>   x.report('regular') { n.times { o.foo } }
> end
>
> $ ruby bench2.rb
>              user     system      total        real
> method_missing  1.030000   0.010000   1.040000 (  1.081370)
> define_method  0.730000   0.010000   0.740000 (  0.773041)
> eval     0.280000   0.000000   0.280000 (  0.303355)
> regular  0.280000   0.000000   0.280000 (  0.296050)
>
> Laurent
>
> On Jun 5, 2007, at 5:47 PM, Laurent Sansonetti wrote:
>
>> Hi,
>>
>> This afternoon I just tried a small experiment in the RubyCocoa
>> core. You know that every time you send a message from Ruby to
>> Objective-C, it goes through #method_missing, which is supposedly
>> slow.
>>
>> I experimented creating the missing method just after
>> #method_missing, so that #method_missing would be called only once
>> (the other messages would be "direct"). I thought it would be a good
>> performance gain.
>>
>> However, from a quick test, it doesn't seem to be better (it's even
>> sometimes worse).
>>
>> Any idea? I attached the patch and the bench test to this message.
>>
>> Laurent
>>
>> <
>> define_missing
>> .diff><bench.rb>_______________________________________________
>> Rubycocoa-devel mailing list
>> Rubyc****@lists*****
>> http://lists.sourceforge.jp/mailman/listinfo/rubycocoa-devel
>
> _______________________________________________
> Rubycocoa-devel mailing list
> Rubyc****@lists*****
> http://lists.sourceforge.jp/mailman/listinfo/rubycocoa-devel




More information about the Rubycocoa-devel mailing list
Back to archive index