为什么 escript 输出不同的结果?

Why does escript outputs different result?

这是一个简单而著名的测试脚本:

-module(processes).
-compile(export_all).

max(N)->
    Max=erlang:system_info(process_limit),
    io:format("the max processes is ~p ~n",[Max]),
    statistics(runtime),
    statistics(wall_clock),
    L=for(1,N,fun()->spawn(fun()->wait() end) end),
    {_,Time1}=statistics(runtime),
    {_,Time2}=statistics(wall_clock),
    lists:foreach(fun(Pid)->Pid!die end,L),
    U1=Time1*1000/N,
    U2=Time2*1000/N,
    io:format("the proecess time is ~p:~p ~n",[U1,U2]).

wait()->
    receive
        die->void
    end.

for(N,N,F)->[F()];
for(I,N,F)->[F()|for(I+1,N,F)].

main([])->
    max(100000).

这是 erl 的输出:

$ erl 
Erlang/OTP 17 [erts-6.2] [source] [64-bit] [smp:2:2] [async-threads:10] [kernel-poll:false]

Eshell V6.2  (abort with ^G)
1> c(processes)
1> processes:max(100000).
* 2: syntax error before: processes
1> c(processes).         
{ok,processes}
2> processes:max(100000).
the max processes is 262144 
the proecess time is 1.1:4.35 
ok

这是 escript 的输出:

$ escript processes.erl
the max processes is 262144 
the proecess time is 47.8:83.4

escript 和 erl 之间的确切区别是什么? 我是erlang的新手,请帮忙!

编辑:

escript运行beam文件时,输出与erl相同的结果:

$ escript processes.beam
the max processes is 262144 
the proecess time is 1.8:3.33

会发生什么?我知道*.beam是编译代码,但是escript不编译之前的脚本运行吗?我还是一头雾水。

区别在于你的第二个 运行 被解释,而你的第一个 运行 被编译。 运行

escript -c processes.erl

你会得到一个基本相同的时间。您还可以通过在脚本中放置指令 -mode(compile). 来获得此行为。

来自the documentation

Execution of interpreted code is slower than compiled code. If much of the execution takes place in interpreted code it may be worthwhile to compile it, even though the compilation itself will take a little while. It is also possible to supply native instead of compile, this will compile the script using the native flag, again depending on the characteristics of the escript this could or could not be worth while.

As mentioned earlier, it is possible to have a script which contains precompiled beam code. In a precompiled script, the interpretation of the script header is exactly the same as in a script containing source code. That means that you can make a beam file executable by prepending the file with the lines starting with #! and %%! mentioned above. In a precompiled script, the function main/1 must be exported.

如果您对预编译选项感兴趣,您可能需要查看构建工具 rebar,它有一个 escriptize 命令可以将您的所有代码转换为 pre-compiled 使用适当的脚本存档 header.

使用interpreting/compiling的机制,可以查看the source code to escript。您将看到 interpret 模式下的 escript 等价于(对某些语法取模)将您的代码逐行粘贴到 erl 交互式解释器中。