当编译后的代码与 shell 计算的代码不同时?
在 Erlang 和 OTP 的实际应用(第 46 页)中,作者在注释中陈述了以下内容:
在某些奇怪的极端情况下,在 shell 中计算的代码的行为可能与编译为模块的一部分时的相同代码略有不同。在这种情况下,编译版本是黄金标准。 shell 在解释表达式时会尽力做同样的事情。
您能想到一个或多个这些奇怪的极端情况吗?这些情况下有哪些细微差别?
In Erlang and OTP in Action (page 46), the authors state the following in a note:
It may happen that in some odd corner case, code evaluated in the shell behaves slightly differently from the same code when compiled as part of a module. In such a case, the compiled version is the gold standard. The shell tries its best to do the exact same thing when it interprets the expressions.
Can you think of one or more of these odd corner cases? Which are the slight differences in those cases?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
最重要的区别是 shell 是解释性的,而编译后的代码是……嗯……编译的。这在函数的执行速度和内存使用方面具有明显的差异。换句话说,您可能会发现解释的变体速度较慢或耗尽了您的所有内存,而编译的版本则不然。
这个问题困扰了很多年轻的 Erlang 程序员。他或她认为 Erlang 与其他语言相比相当慢,而实际上它是解释代码与编译代码的测试。
该段落是一种保护措施。基本上,解释器和编译器应该就函数的所有输入/输出达成一致。但不幸的是情况并非总是如此。实际上,解释器和编译器是不同的执行引擎,因此可能有所不同。如果通过 HiPE 进行本机编译,变化可能会更大。通常问题会出现在 IEEE 754 浮点数周围。
The most important difference is that the shell is interpreted whereas the compiled code is... well.. compiled. This has observable difference in the execution speed and memory usage of the function. In other words, you may find that the interpreted variant is slower or uses up all your memory while the compiled version does not.
This problem has bitten many a young Erlang programmer. He or she thinks Erlang is rather slow compared to other languages, while it in reality is a test of interpreted code against compiled.
The paragraph is a protective measure. Basically the interpreter and compiler ought to agree on all input/output of a function. But unfortunately that is not always the case. In practice the interpreter and compiler are distinct execution engines and may thus differ. If you native-compile through HiPE the changes might be even larger. Usually problems arise around IEEE 754 floating point numbers.
erlang 解释器 erl_eval 非常努力地表现得与编译代码完全相同。如果没有,则很可能是一个错误。
除了一种情况,那就是接收消息。编译后的代码可以访问内部指令来访问和操作消息队列。口译员不能这样做。它必须: 实际上从队列中删除消息(或多或少带有
receive X -> X end
);测试它们以查看它们是否与接收模式匹配;保留那些不匹配的;并将所有当前不需要的消息放回到队列中(通过接收所有消息,然后将它们发送回自身)。这意味着在很短的时间内,如果消息到达,它可能不会像编译代码那样最终出现在消息队列中的同一位置。The erlang interpreter,
erl_eval
, tries very hard to behave exactly like compiled code. If it doesn't it is most likely a bug.Except in one case and that is receiving messages. Compiled code can access the internal instructions to access and manipulate the message queue. The interpreter can not do this. It must: actually remove messages from the queue (more or less with
receive X -> X end
); test them to see if they match the receive patterns; keep those that don't match; and put back all the currently unwanted messages into the queue (by receiving all messages and then sending them back to itself). This means that there is a short time in which if a message arrives it may not end up in the same place in the message queue as for compiled code.