how to make eval() faster?

Z

Zd Yu

I use eval() to dynamically calculate performance metrics.

for example:
I have one configuration file that defines many performance metric
formulas, like IPC=instructions/cpu_cycles.

I also have another data file that contains many data samples, and I
just call the eval() for every data sample.

The problem is that I found eval() is really slow. is there a way to
make it faster?
 
J

Joel VanderWerf

I use eval() to dynamically calculate performance metrics.

for example:
I have one configuration file that defines many performance metric
formulas, like IPC=instructions/cpu_cycles.

I also have another data file that contains many data samples, and I
just call the eval() for every data sample.

The problem is that I found eval() is really slow. is there a way to
make it faster?

Can you eval your formulas into methods, and call the methods on the
data samples?
 
Z

Zd Yu

Joel VanderWerf wrote in post #998154:
Can you eval your formulas into methods, and call the methods on the
data samples?

No. I need flexibility, i.e., allow users to define their own formulas
in the configuration file.
 
M

Markus Schirp

The configuration file can be plain ruby!
You can define your own DSL to manage the formulars.
So you can load the file once and the formulars do not have to be evaled...
 
Z

Zd Yu

Markus Schirp wrote in post #998159:
The configuration file can be plain ruby!
You can define your own DSL to manage the formulars.
So you can load the file once and the formulars do not have to be
evaled...

Nice catch. Actually I did try to implement it as DSL at the beginning,
but finally I realized it is difficult to implement such a DSL in my
problem. So at last I went to the XML format configuration way.

Below is the post I asked about DSL in 5 months ago:
http://www.ruby-forum.com/topic/696974#new
 
Z

Zd Yu

I just came up with an idea: I can parse the XML configuration file and
generate a .rb file on the fly then invoke the rb file.

Although it brings much extra efforts, it can fix the performance issue.
 
M

Markus Schirp

Too difficult?

The most "stupid simple" dsl is IMHO block based...

yourlib.rb
----------

module Yourlib
class << self
def define_processor(key,&block)
processors << [key,&block]
end

def processors
@processors ||= []
end

def run(row) # row should be an hash
processors.each do |key,block|
input[key]=block.call(row)
end
end
end
end

settings.rb
-----------

require 'yourlib'

Yourlib.define_processor :eek:utcome_a do |current|
current[:event_a] * current[:event_b]
end

Yourlib.define_processor :eek:utcome_b do |current|
current[:eek:utcome_b] = current[:event_b] * current[:eek:utcome_a]
end

File.readlines(somepath) do |row|
out = Yourlib.run(preprocess(row))
do_something_fancy(out)
end

As long as your users do not use outcomes before they are produced you
can do calculations based on the outcomes...

If you need namespacing etc you can simply make an convention about the
output key names... and maybe about the input keys too... or try to add
(nested) namespacing.

I new this DSL is messy and redundant in usage, but a better approach
than using eval ;)

Regards,

Markus
 
S

Stu

I was going to suggest a creating a tmp file with a generator. create
a sort of cached methods type thing.

This may fix your issue.
 
X

Xavier Noria

No need to create a temp file. Unless the resulting code is huge, you can ge=
nerate in memory and eval (once) the whole thing.

Top-posted from my iPad
 
R

Robert Klemme

Joel VanderWerf wrote in post #998154:

No. I need flexibility, i.e., allow users to define their own formulas
in the configuration file.

I believe you did not fully understand what Joel suggested. You do
have that flexibility and you need to invoke eval only _once_ per
formula (for the initial compilation of the formula) but not for every
evaluation. Example:

# really too simplistic!
formulas = Hash.new do |h, form|
expr = form.sub(/\A.*?=\s*/, '')
vars = expr.scan(/[a-z]\w*/i).uniq
code = "lambda do |#{vars.join(', ')}| #{expr} end"
p vars, code
h[form] = eval(code)
end

# test
[
'x = y * 2 + z',
'z = y * x',
].each do |f|
puts f

10.times do |i|
printf "%s: %d %d => %f\n", f, i, i*2, formulas[f][i, i*2]
end
end

I'd prefer the DSL approach though.

Kind regards

robert
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top