From: Rick DeNatale Date: 2007-03-14T02:56:13+09:00 Subject: Re: get object from its object-specific class? On 3/13/07, Trans 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. rick@frodo:/public/rubyscripts/getsinginst$ ruby gsi.rb {:a=>1} true Rehearsal ---------------------------------------------------------- ObjectSpace 3.270000 0.100000 3.370000 ( 3.469175) singleton_method_added 4.450000 0.110000 4.560000 ( 4.580452) primitive 0.040000 0.000000 0.040000 ( 0.046098) ------------------------------------------------- total: 7.970000sec user system total real ObjectSpace 2.300000 0.050000 2.350000 ( 2.352730) singleton_method_added 4.430000 0.070000 4.500000 ( 4.510719) primitive 0.040000 0.000000 0.040000 ( 0.037970) -- Rick DeNatale My blog on Ruby http://talklikeaduck.denhaven2.com/