开发者

eval() versus if() -- is there a performance difference?

My questio开发者_如何学Gon specifically is for Perl but I would like to be enlightened for most languages.

Is there an actual difference (performance-wise and efficiency-wise) between using an eval() function, versus an if() statement?

eval(-e /path/to/file) or die "file doesn't exist";
if (! -e /path/to/file) { die "file doesn't exist"; }


First of all, don't micro-optimize like this. It is far more important to write code that you can most easily follow the sense of. Keeping this in mind will result in fewer bugs, and avoiding one bug is more important than saving a great number of nanoseconds.

That said, you can examine how perl compiles things like so:

$ perl -MO=Concise,-exec -e '-e "/path/to/file" or die "file doesn\x27t exist";'
1  <0> enter 
2  <;> nextstate(main 1 -e:1) v:{
3  <$> const[PV "/path/to/file"] s
4  <1> ftis sK/1
5  <|> or(other->6) vK/1
6      <0> pushmark s
7      <$> const[PV "file doesn't exist"] s
8      <@> die[t2] vK/1
9  <@> leave[1 ref] vKP/REFC
-e syntax OK

$ perl -MO=Concise,-exec -e 'if ( ! -e "/path/to/file") { die "file doesn\x27t exist"; }'
1  <0> enter 
2  <;> nextstate(main 3 -e:1) v:{
3  <$> const[PV "/path/to/file"] s
4  <1> ftis sK/1
5  <1> not sK/1
6  <|> and(other->7) vK/1
7      <0> enter v
8      <;> nextstate(main 1 -e:1) v:{
9      <0> pushmark s
a      <$> const[PV "file doesn't exist"] s
b      <@> die[t2] vK/1
c      <@> leave vKP
d  <@> leave[1 ref] vKP/REFC
-e syntax OK

You can see some trivial extra operations involved in the second for the logical not of the result of -e, entering and leaving the {} block, and for having the die as a separate statement. That separate statement can be useful; if you are stepping through the code in the debugger, it stops before dieing.

Using Perl 5.12+ or using unless instead of if ! in older version of Perl removes the not:

$ perl -MO=Concise,-exec -e 'unless (-e "/path/to/file") { die "file doesn\x27t exist"; }'
1  <0> enter 
2  <;> nextstate(main 3 -e:1) v:{
3  <$> const[PV "/path/to/file"] s
4  <1> ftis sK/1
5  <|> or(other->6) vK/1
6      <0> enter v
7      <;> nextstate(main 1 -e:1) v:{
8      <0> pushmark s
9      <$> const[PV "file doesn't exist"] s
a      <@> die[t2] vK/1
b      <@> leave vKP
c  <@> leave[1 ref] vKP/REFC
-e syntax OK

Using a statement modifier produces the same results as the -e ... or die code:

$ perl -MO=Concise,-exec -e 'die "file doesn\x27t exist" unless -e "/path/to/file";'
1  <0> enter 
2  <;> nextstate(main 1 -e:1) v:{
3  <$> const[PV "/path/to/file"] s
4  <1> ftis sK/1
5  <|> or(other->6) vK/1
6      <0> pushmark s
7      <$> const[PV "file doesn't exist"] s
8      <@> die[t2] vK/1
9  <@> leave[1 ref] vKP/REFC
-e syntax OK


The string eval (eval EXPR) requires perl to compile your expression at runtime each time it is executed, which will be a lot more expensive than evaluating a pre-compiled expression. This is also true for any language that provides a similar run-time eval mechanism (JavaScript, Ruby, Python?)

In both the string eval and the block eval (eval { BLOCK }), perl sets up an error handler that sets $@ and returns to the end of the eval statement in the event of an otherwise fatal error. Again, this is more expensive than simply executing BLOCK, in Perl and in any other language with the facility to trap exceptions (Python, Java).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜