For some reasons I extensively use this technique:
obj = MyClass.new(...)
obj.instance_eval{
def my_cool_method
end
}
#create 1000 clones of the obj, call #my_cool_method
(1..1000).collect{
clon = obj.clone
clon.my_cool_method
}
The problem is ruby-prof shows each clone's #my_cool_method as separate one in the report, so I see 1000 lines with 1 calls of #my_cool_method instead of 1 line with 1000 calls. Is it bug or by design? May this problem be result of the fact I use latest Ruby 1.9 version?
Thanks.
V.
This is what I've found in the sources:
My_cool_method is a singleton instance method (not an ordinary
instance method). singleton methods are cloned by creating proxy
method, so they are not identical.
object.c: rb_obj_clone()
class.c : rb_singleton_class_clone() and clone_method()
try:
o1 = Object.new
# this creates singleton method
o1.instance_eval { def m ; end }
o2 = o1.clone
p o1.method(:m) #=> #<Method: #<Object:0x393c328>.m>
p o2.method(:m) #=> #<Method: #<Object:0x393c198>(#<Object:0x393c328>).m>
o3 = o1.clone
p o3.method(:m) #=> #<Method: #<Object:0x393bcd4>(#<Object:0x393c328>).m>
# now this creates normal method:
o1.class.module_eval { def c ; end }
p o1.method(:c) #=> #<Method: Object#c>
p o2.method(:c) #=> #<Method: Object#c>
p o3.method(:c) #=> #<Method: Object#c>
However it should be possible to patch ruby-prof to take account for this.
IMHO the most simple way is to define normal instance methods via
obj.class.module_eval, i.e. MyClass.module_eval.
(Please note that I might be wrong, I'm no expert on ruby internals,
this is what I learned in a few minutes looking into sources...)
···
On 10/26/06, Victor 'Zverok' Shepelev <vshepelev@imho.com.ua> wrote:
For some reasons I extensively use this technique:
obj = MyClass.new(...)
obj.instance_eval{
def my_cool_method
end
}
#create 1000 clones of the obj, call #my_cool_method
(1..1000).collect{
clon = obj.clone
clon.my_cool_method
}
The problem is ruby-prof shows each clone's #my_cool_method as separate one in the report, so I see 1000 lines with 1 calls of #my_cool_method instead of 1 line with 1000 calls. Is it bug or by design? May this problem be result of the fact I use latest Ruby 1.9 version?
Jan Svitok (jan.svitok@gmail.com)
26/10/2006 13:56:01
> For some reasons I extensively use this technique:
>
> obj = MyClass.new(...)
> obj.instance_eval{
> def my_cool_method
> end
> }
>
> #create 1000 clones of the obj, call #my_cool_method
> (1..1000).collect{
> clon = obj.clone
> clon.my_cool_method
> }
>
> The problem is ruby-prof shows each clone's #my_cool_method as separate
> one in the report, so I see 1000 lines with 1 calls of #my_cool_method
> instead of 1 line with 1000 calls. Is it bug or by design? May this
> problem be result of the fact I use latest Ruby 1.9 version?
This is what I've found in the sources:
My_cool_method is a singleton instance method (not an ordinary
instance method). singleton methods are cloned by creating proxy
method, so they are not identical.
OK, I've got it.
Thanks.
IMHO the most simple way is to define normal instance methods via
obj.class.module_eval, i.e. MyClass.module_eval.
Not for me, unfortunately 
One of reasons, why I use those strange techniques, is to have different sets of methods in different sets of objects of same class.
More specially, all those objects are HTML DOM nodes, and I want to have #cell(col, row) method for <table> node, #click method for <button> node and even more special cases, like have some special methods for <table class=grid>. My approach is on-the-fly per-CSS-selector extending of certain nodes, and it works well, except for profiling 
The issue still open.
V.
···
On 10/26/06, Victor 'Zverok' Shepelev <vshepelev@imho.com.ua> wrote:
Maybe you can create new subclasses instead:
my_new_class = Class.new(MyClass)
my_new_class.module_eval {...}
and optionally
Object.const_set(my_new_class_name, mynewclass)
NB: class_eval is an alias for module_eval.
···
On 10/26/06, Victor 'Zverok' Shepelev <vshepelev@imho.com.ua> wrote:
Jan Svitok (jan.svitok@gmail.com)
26/10/2006 13:56:01
> On 10/26/06, Victor 'Zverok' Shepelev <vshepelev@imho.com.ua> wrote:
> > For some reasons I extensively use this technique:
> >
> > obj = MyClass.new(...)
> > obj.instance_eval{
> > def my_cool_method
> > end
> > }
> >
> > #create 1000 clones of the obj, call #my_cool_method
> > (1..1000).collect{
> > clon = obj.clone
> > clon.my_cool_method
> > }
> >
> > The problem is ruby-prof shows each clone's #my_cool_method as separate
> > one in the report, so I see 1000 lines with 1 calls of #my_cool_method
> > instead of 1 line with 1000 calls. Is it bug or by design? May this
> > problem be result of the fact I use latest Ruby 1.9 version?
>
> This is what I've found in the sources:
> My_cool_method is a singleton instance method (not an ordinary
> instance method). singleton methods are cloned by creating proxy
> method, so they are not identical.
>
OK, I've got it.
Thanks.
> IMHO the most simple way is to define normal instance methods via
>
> obj.class.module_eval, i.e. MyClass.module_eval.
Not for me, unfortunately 
One of reasons, why I use those strange techniques, is to have different sets of methods in different sets of objects of same class.
More specially, all those objects are HTML DOM nodes, and I want to have #cell(col, row) method for <table> node, #click method for <button> node and even more special cases, like have some special methods for <table class=grid>. My approach is on-the-fly per-CSS-selector extending of certain nodes, and it works well, except for profiling 
The issue still open.
Will something like this meet your needs?
rick@frodo:/public/rubyscripts$ cat mycool.rb
class MyClass
end
module MyCoolModule
def my_cool_method
end
end
obj = MyClass.new
obj.extend MyCoolModule
#create 1000 clones of the obj, call #my_cool_method
(1..1000).collect{
clon = obj.clone
clon.my_cool_method
}
rick@frodo:/public/rubyscripts$ ruby -r profile mycool.rb
% cumulative self self total
time seconds seconds calls ms/call ms/call name
53.04 0.61 0.61 1 610.00 1140.00 Range#each
28.70 0.94 0.33 1000 0.33 0.40 Kernel.clone
11.30 1.07 0.13 1000 0.13 0.13
MyCoolModule.my_cool_method
6.09 1.14 0.07 1000 0.07 0.07 Kernel.initialize_copy
0.00 1.14 0.00 1 0.00 0.00 Module#extended
0.00 1.14 0.00 1 0.00 0.00 Kernel.extend
0.00 1.14 0.00 1 0.00 0.00 Class#new
0.00 1.14 0.00 1 0.00 0.00 Class#inherited
0.00 1.14 0.00 1 0.00 1140.00 Enumerable.collect
0.00 1.14 0.00 1 0.00 0.00 Object#initialize
0.00 1.14 0.00 1 0.00 0.00 Module#extend_object
0.00 1.14 0.00 1 0.00 0.00 Module#method_added
0.00 1.15 0.00 1 0.00 1150.00 #toplevel
rick@frodo:/public/rubyscripts$
···
On 10/26/06, Victor 'Zverok' Shepelev <vshepelev@imho.com.ua> wrote:
Jan Svitok (jan.svitok@gmail.com)
26/10/2006 13:56:01
> On 10/26/06, Victor 'Zverok' Shepelev <vshepelev@imho.com.ua> wrote:
> > For some reasons I extensively use this technique:
> >
> > obj = MyClass.new(...)
> > obj.instance_eval{
> > def my_cool_method
> > end
> > }
> >
> > #create 1000 clones of the obj, call #my_cool_method
> > (1..1000).collect{
> > clon = obj.clone
> > clon.my_cool_method
> > }
> >
> > The problem is ruby-prof shows each clone's #my_cool_method as separate
> > one in the report, so I see 1000 lines with 1 calls of #my_cool_method
> > instead of 1 line with 1000 calls. Is it bug or by design? May this
> > problem be result of the fact I use latest Ruby 1.9 version?
>
> This is what I've found in the sources:
> My_cool_method is a singleton instance method (not an ordinary
> instance method). singleton methods are cloned by creating proxy
> method, so they are not identical.
>
OK, I've got it.
Thanks.
> IMHO the most simple way is to define normal instance methods via
>
> obj.class.module_eval, i.e. MyClass.module_eval.
Not for me, unfortunately 
One of reasons, why I use those strange techniques, is to have different sets of methods in different sets of objects of same class.
More specially, all those objects are HTML DOM nodes, and I want to have #cell(col, row) method for <table> node, #click method for <button> node and even more special cases, like have some special methods for <table class=grid>. My approach is on-the-fly per-CSS-selector extending of certain nodes, and it works well, except for profiling 
--
Rick DeNatale
My blog on Ruby
http://talklikeaduck.denhaven2.com/
Jan Svitok (jan.svitok@gmail.com)
26/10/2006 14:38:01
> One of reasons, why I use those strange techniques, is to have different
> sets of methods in different sets of objects of same class.
>
> More specially, all those objects are HTML DOM nodes, and I want to have
> #cell(col, row) method for <table> node, #click method for <button> node
> and even more special cases, like have some special methods for <table
> class=grid>. My approach is on-the-fly per-CSS-selector extending of
> certain nodes, and it works well, except for profiling 
>
> The issue still open.
Maybe you can create new subclasses instead:
my_new_class = Class.new(MyClass)
my_new_class.module_eval {...}
and optionally
Object.const_set(my_new_class_name, mynewclass)
Hmmm... Sounds reasonable. I'll try.
Thanks, Jan!
V.