eval() 与 if() ——有性能差异吗?

发布于 2024-11-28 01:11:10 字数 220 浏览 2 评论 0原文

我的问题专门针对 Perl,但我希望对大多数语言有所启发。

使用 eval() 函数与 if() 语句之间是否存在实际差异(性能方面和效率方面)?

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

My question 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"; }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

吃颗糖壮壮胆 2024-12-05 01:11:10

首先,不要像这样进行微观优化。编写您最容易理解的代码更为重要。牢记这一点将减少错误,避免一个错误比节省大量纳秒更重要。

也就是说,您可以检查 perl 如何编译如下内容:

$ 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  <
gt; const[PV "/path/to/file"] s
4  <1> ftis sK/1
5  <|> or(other->6) vK/1
6      <0> pushmark s
7      <
gt; 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  <
gt; 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      <
gt; const[PV "file doesn't exist"] s
b      <@> die[t2] vK/1
c      <@> leave vKP
d  <@> leave[1 ref] vKP/REFC
-e syntax OK

您可以看到第二个中涉及 -e 结果的逻辑非的一些琐碎的额外操作,进入和离开 {} 块,并将骰子作为单独的声明。这个单独的声明可能很有用;如果您在调试器中单步执行代码,它会在死亡之前停止。

在旧版本的 Perl 中使用 Perl 5.12+ 或使用 unless 代替 if ! 会删除 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  <
gt; 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      <
gt; const[PV "file doesn't exist"] s
a      <@> die[t2] vK/1
b      <@> leave vKP
c  <@> leave[1 ref] vKP/REFC
-e syntax OK

使用语句修饰符会产生与以下相同的结果-e ... or die 代码:

$ 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  <
gt; const[PV "/path/to/file"] s
4  <1> ftis sK/1
5  <|> or(other->6) vK/1
6      <0> pushmark s
7      <
gt; const[PV "file doesn't exist"] s
8      <@> die[t2] vK/1
9  <@> leave[1 ref] vKP/REFC
-e syntax OK

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  <
gt; const[PV "/path/to/file"] s
4  <1> ftis sK/1
5  <|> or(other->6) vK/1
6      <0> pushmark s
7      <
gt; 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  <
gt; 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      <
gt; 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  <
gt; 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      <
gt; 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  <
gt; const[PV "/path/to/file"] s
4  <1> ftis sK/1
5  <|> or(other->6) vK/1
6      <0> pushmark s
7      <
gt; const[PV "file doesn't exist"] s
8      <@> die[t2] vK/1
9  <@> leave[1 ref] vKP/REFC
-e syntax OK
仅冇旳回忆 2024-12-05 01:11:10

字符串eval (eval EXPR)需要perl在每次执行时在运行时编译你的表达式,这比评估预编译的表达式要昂贵得多。对于任何提供类似运行时 eval 机制的语言(JavaScript、Ruby、Python?),在字符串 eval 和块 eval 中也是如此

eval >eval { BLOCK }),perl 设置一个错误处理程序,设置 $@ 并在出现 else 情况时返回到 eval 语句的末尾致命错误。同样,这比在 Perl 和任何其他具有捕获异常功能的语言(Python、Java)中简单执行 BLOCK 的成本更高。

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文