[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

ruby-prof vs. Object#clone

Victor 'Zverok' Shepelev

10/26/2006 9:51:00 AM

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.


5 Answers

Jano Svitok

10/26/2006 10:56:00 AM

0

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.

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...)

Victor 'Zverok' Shepelev

10/26/2006 11:19:00 AM

0

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.

V.


Jano Svitok

10/26/2006 11:38:00 AM

0

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.

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.

Victor 'Zverok' Shepelev

10/26/2006 11:44:00 AM

0

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.


Rick DeNatale

10/26/2006 4:08:00 PM

0

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 :(

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$

--
Rick DeNatale

My blog on Ruby
http://talklikeaduck.denh...