[#28561] Ruby::DL vs Ruby::FFI — Aston <blackapache512-ticket@...>

Ruby.DL and FFI libraries are great for programmers like me who are not internet programmers, but are more interested in scientific and number processing etc.

11 messages 2010/03/08

[#28686] trunk (26947) build fail with msys/mingw/vista — Jon <jon.forums@...>

I get the following build failure when msysgit's "c:\git\cmd" dir is on PATH.

8 messages 2010/03/16

[#28687] [Bug #2973] rb_bug - Segmentation fault - error.c:213 — rudolf gavlas <redmine@...>

Bug #2973: rb_bug - Segmentation fault - error.c:213

10 messages 2010/03/16

[#28735] [Bug #2982] Ruby tries to link with both openssl and readline — Lucas Nussbaum <redmine@...>

Bug #2982: Ruby tries to link with both openssl and readline

16 messages 2010/03/18

[#28736] [Bug #2983] Ruby (GPLv2 only) tries to link to with readline (now GPLv3) — Lucas Nussbaum <redmine@...>

Bug #2983: Ruby (GPLv2 only) tries to link to with readline (now GPLv3)

10 messages 2010/03/18

[#28907] [Bug #3000] Open SSL Segfaults — Christian Höltje <redmine@...>

Bug #3000: Open SSL Segfaults

19 messages 2010/03/23

[#28924] [Bug #3005] Ruby core dump - [BUG] rb_sys_fail() - errno == 0 — Sebastian YEPES <redmine@...>

Bug #3005: Ruby core dump - [BUG] rb_sys_fail() - errno == 0

10 messages 2010/03/24

[#28954] [Feature #3010] slow require gems in ruby 1.9.1 — Miao Jiang <redmine@...>

Feature #3010: slow require gems in ruby 1.9.1

15 messages 2010/03/24

[#29179] [Bug #3071] Convert rubygems and rdoc to use psych — Aaron Patterson <redmine@...>

Bug #3071: Convert rubygems and rdoc to use psych

10 messages 2010/03/31

[ruby-core:28767] Re: [Feature #2065] An ancestors iterator

From: Yusuke ENDOH <mame@...>
Date: 2010-03-19 03:41:34 UTC
List: ruby-core #28767
Hi Simon,

2010/3/19 Simon Chiang <redmine@ruby-lang.org>:
> This is for 100k iterations, so no it's not a bottleneck but likewise that's not why I make this request. I make the request because it would be significantly faster to not generate the ancestors array each time (~20% in this case, which illustrates what is probably the maximum increase for getting an each_ancestor iterator).

I cannot get your point.  If you admit it is not bottleneck, I wonder
why you hope it faster.
You should know adding a method is not free in terms of maintenance.


> Ok, I attached a benchmark that is designed to measure the time required for generating the ancestors array.

Thanks, I could understand what you want to do.

If you want speed at any rate, how about manual search by using
Class#superclass?
It is probably faster than each_ancestor because it does not
yield a block.


  module Dsl2
    def self.extended(base)
      base.registry ||= {}
    end

    def inherited(base)
      base.registry ||= {}
    end

    attr_accessor :registry

    def set(key, value)
      registry[key] = value
    end

    def value(key)
      klass = self
      while klass
        if klass.registry.has_key?(key)
          return klass.registry[key]
        end
        klass = klass.superclass
      end
    end
  end


Benchmark without cache
                          user     system      total        real
A.value(:one)         0.340000   0.000000   0.340000 (  0.340906)
B.value(:two)         0.340000   0.000000   0.340000 (  0.349000)
C.value(:three)       0.360000   0.000000   0.360000 (  0.357215)

Benchmark with cache
                          user     system      total        real
A.value(:one)         0.240000   0.000000   0.240000 (  0.235161)
B.value(:two)         0.230000   0.000000   0.230000 (  0.236722)
C.value(:three)       0.240000   0.000000   0.240000 (  0.233931)
Array.new             0.080000   0.000000   0.080000 (  0.084003)

Benchmark with manual search
                          user     system      total        real
A2.value(:one)        0.130000   0.000000   0.130000 (  0.122530)
B2.value(:two)        0.120000   0.000000   0.120000 (  0.120361)
C2.value(:three)      0.110000   0.000000   0.110000 (  0.119009)

-- 
Yusuke ENDOH <mame@tsg.ne.jp>

Attachments (1)

benchmark.rb (2.58 KB, text/x-ruby)
require 'benchmark'

# A basic version of a dsl that registers key-value pairs onto a Class.  When
# looking up a key-value pair, Classes that use the dsl will check the
# registry of each ancestor in order, as if looking up a method.
#
# Call cache_ancestors! to cache the ancestry and speedup lookup.
module Dsl
  def self.extended(base)
    base.registry ||= {}
    base.cache = nil
  end
  
  def inherited(base)
    base.registry ||= {}
    base.cache = nil
  end
  
  attr_accessor :registry
  attr_accessor :cache
  
  def set(key, value)
    registry[key] = value
  end
  
  def value(key)
    each_ancestor do |ancestor|
      if ancestor.registry.has_key?(key)
        return ancestor.registry[key]
      end
    end
  end
  
  def cache_ancestors!
    @cache = ancestors
  end
  
  def each_ancestor
    (cache || ancestors).each {|ancestor| yield(ancestor)}
  end
end

# Now the benchmarks, first without caching (ie regenerate ancestors each
# time), then with caching to model performance with an each_ancestor method.
puts "Benchmark without cache"

class A
  extend Dsl
  set(:one, 1)
end

class B < A
  set(:two, 2)
end

class C < B
  set(:three, 3)
end

Benchmark.bm(20) do |x|
  n = 100000
  
  x.report "A.value(:one)" do
    n.times { A.value(:one) }
  end
  
  x.report "B.value(:two)" do
    n.times { B.value(:two) }
  end
  
  x.report "C.value(:three)" do
    n.times { C.value(:three) }
  end
end

puts
puts "Benchmark with cache"
A.cache_ancestors!
B.cache_ancestors!
C.cache_ancestors!

Benchmark.bm(20) do |x|
  n = 100000
  
  x.report "A.value(:one)" do
    n.times { A.value(:one) }
  end
  
  x.report "B.value(:two)" do
    n.times { B.value(:two) }
  end
  
  x.report "C.value(:three)" do
    n.times { C.value(:three) }
  end
  
  x.report "Array.new" do
    n.times { Array.new }
  end
end


module Dsl2
  def self.extended(base)
    base.registry ||= {}
  end
  
  def inherited(base)
    base.registry ||= {}
  end
  
  attr_accessor :registry
  
  def set(key, value)
    registry[key] = value
  end
  
  def value(key)
    klass = self
    while klass
      if klass.registry.has_key?(key)
        return klass.registry[key]
      end
      klass = klass.superclass
    end
  end
end

puts
puts "Benchmark with manual search"

class A2
  extend Dsl2
  set(:one, 1)
end

class B2 < A2
  set(:two, 2)
end

class C2 < B2
  set(:three, 3)
end

Benchmark.bm(20) do |x|
  n = 100000
  
  x.report "A2.value(:one)" do
    n.times { A2.value(:one) }
  end
  
  x.report "B2.value(:two)" do
    n.times { B2.value(:two) }
  end
  
  x.report "C2.value(:three)" do
    n.times { C2.value(:three) }
  end
end

In This Thread

Prev Next