[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

Caching eval() for reuse to gain performance ?

Neville Burnell

6/27/2005 6:11:00 AM

Hi,

I have an active record collection and I need to 'eval' a string against
each row from the collection. Instead of processing the 'eval' for each
row, I was thinking to 'cache' the eval into a Proc to for reuse, ie:

irb(main):001:0> @a = 1
=> 1
irb(main):002:0> @b = 7
=> 7
irb(main):003:0> c = %q{ @a + @b }
=> " @a + @b "
irb(main):004:0> d = Proc.new { eval c }
=> #<Proc:0x02ad1240@(irb):4>
irb(main):005:0> d.call
=> 8
irb(main):006:0> @a = 2
=> 2
irb(main):007:0> d.call
=> 9
irb(main):008:0>

Is my assumption that eval is relatively expensive, and that a Proc call
is fast correct?
Any suggestions on how to do this better?

Thanks

Nev
3 Answers

Kent Sibilev

6/27/2005 6:23:00 AM

0

I might be wrong here, but I think you proc method is not faster or
it's even slower than plain eval method. Every time you call a proc,
eval gets called as well.

You can try to define your proc like so:

p = eval "lambda{#{c}}"

Kent.

On 6/27/05, Neville Burnell <Neville.Burnell@bmsoft.com.au> wrote:
> Hi,
>
> I have an active record collection and I need to 'eval' a string against
> each row from the collection. Instead of processing the 'eval' for each
> row, I was thinking to 'cache' the eval into a Proc to for reuse, ie:
>
> irb(main):001:0> @a = 1
> => 1
> irb(main):002:0> @b = 7
> => 7
> irb(main):003:0> c = %q{ @a + @b }
> => " @a + @b "
> irb(main):004:0> d = Proc.new { eval c }
> => #<Proc:0x02ad1240@(irb):4>
> irb(main):005:0> d.call
> => 8
> irb(main):006:0> @a = 2
> => 2
> irb(main):007:0> d.call
> => 9
> irb(main):008:0>
>
> Is my assumption that eval is relatively expensive, and that a Proc call
> is fast correct?
> Any suggestions on how to do this better?
>
> Thanks
>
> Nev
>
>


netghost

6/27/2005 7:43:00 PM

0

That won't gain you any effiecency. Assuming that you're doing the
same statement for each record perhaps you'd be better off with
something along the lines of:

irb(main):001:0> p = proc{|a,b| a+b }
=> #<Proc:0x000583ec@(irb):1>
irb(main):002:0> p.call(1,5)
=> 6

You might just need to rethink your approach a little.
.adam sanderson

Kent Sibilev

6/27/2005 8:01:00 PM

0

Care to explain? The idea was that you don't know beforehand what code
gets called by proc.

I don't like both approaches, but:

$ cat eval_cache.rb
require 'benchmark'

c = '@a + @b'
@a, @b = 1, 2
p1 = lambda { eval c }
p2 = eval "lambda { #{c} }"

Benchmark.bm do |x|
x.report do
100000.times {p1.call}
end
x.report do
100000.times {p2.call}
end
end
$ ruby eval_cache.rb

user system total real
0.480000 0.000000 0.480000 ( 0.480000)
0.160000 0.000000 0.160000 ( 0.161000)

Kent.

On 6/27/05, Adam Sanderson <netghost@gmail.com> wrote:
> That won't gain you any effiecency. Assuming that you're doing the
> same statement for each record perhaps you'd be better off with
> something along the lines of:
>
> irb(main):001:0> p = proc{|a,b| a+b }
> => #<Proc:0x000583ec@(irb):1>
> irb(main):002:0> p.call(1,5)
> => 6
>
> You might just need to rethink your approach a little.
> .adam sanderson
>
>
>