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)
···
On 3/13/07, Trans <transfire@gmail.com> wrote:
--
Rick DeNatale
My blog on Ruby
http://talklikeaduck.denhaven2.com/