On Mar 13, 1:56 pm, "Rick DeNatale" <rick.denat... / gmail.com> wrote:
> On 3/13/07, Trans <transf... / gmail.com> wrote:
> Two approaches with a benchmark.
>
> And as I surmised, there's a really quick way to do this with a
> relatively simple extension (at least for ruby1.8, I haven't looked at
> this on 1.9).
>
> rick@frodo:/public/rubyscripts/getsinginst$ cat get_sing_inst.c
> #include "ruby.h"
>
> static VALUE singleton_instance(VALUE obj)
> {
>   if (BUILTIN_TYPE(obj) == T_CLASS && FL_TEST(obj, FL_SINGLETON)) {
>       return rb_iv_get(obj, "__attached__");
>   }
>   rb_raise(rb_eTypeError, "not a singleton class");
>
> }
>
> void Init_get_sing_inst()
> {
>   rb_define_method(rb_cClass, "singleton_instance", singleton_instance, 0);
>
> }
>
> rick@frodo:/public/rubyscripts/getsinginst$ cat gsi.rb
> require 'get_sing_inst'
>
> h = {:a => 1}
> sc = class << h
>     def foo
>     end
>
>     self
>    end
>
> p sc.singleton_instance
> p sc.singleton_instance.object_id == h.object_id
>
> def instance_of_singleton_class_1(sc)
>     ObjectSpace.each_object(sc) do |obj|
>       return obj
>     end
>   end
>
>   def instance_of_singleton_class_2(sc)
>     obj = nil
>     sc.class_eval do
>       if instance_methods(false).include?("singleton_method_added")
>         org = instance_method("singleton_method_added")
>         remove_method("singleton_method_added")
>       end
>       define_method("singleton_method_added") do |m|
>         obj = self
>       end
>       remove_method("singleton_method_added")
>       define_method("singleton_method_added", org) if org
>     end
>     obj
>   end
>
> require "benchmark"
>
>   Benchmark.bmbm do |bm|
>     bm.report "ObjectSpace" do
>       10000.times do instance_of_singleton_class_1(sc) end
>     end
>     bm.report "singleton_method_added" do
>       10000.times do instance_of_singleton_class_2(sc) end
>     end
>     bm.report "primitive" do
>       10000.times do sc.singleton_instance end
>     end
>   end
>
> And now for the benchmark results,  note that I'm doing 10 times as
> many interations as Trans did, 10000 vs. 1000, the primitive is on the
> order of two orders of magnitude faster than either of the other
> approaches.

Actually, you mean Pit. He did the benchmarks. This is definitely the
way to do it right though. I would submit this to ruby-core mailing
list and see how it takes over there.

T.