kingluo
kingluo

Reputation: 1781

Why does escript outputs different result?

It's a simple and well-known test script:

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

Here is the output of 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

Here is the output of escript:

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

What's the exact difference between escript and erl? I'm a newbie of erlang, please help!

Edit:

When escript runs beam file, it output same result as erl:

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

What happens? I know *.beam is compiled codes, but escript does not compile the script before running it? I'm still confused.

Upvotes: 1

Views: 174

Answers (1)

Nathaniel Waisbrot
Nathaniel Waisbrot

Reputation: 24493

The difference is that your second run is being interpreted, while your first run was compiled. Run

escript -c processes.erl

and you'll get a time that is basically the same. You can also get this behavior by putting the directive -mode(compile). in your script.

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

If you're interested in the precompiled option, you may want to check out the build tool rebar, which has an escriptize command for turning all your code into a pre-compiled archive with the appropriate escript header.

For the mechanism of interpreting/compiling used, you can check out the source code to escript. What you'll see is that escript in interpret mode is equivalent (modulo some syntax) to pasting your code into the erl interactive interpreter line by line.

Upvotes: 1

Related Questions