プログラミングErlangからのまとめ

以前,ejabberdを使ってみるのでErlangをちょっとかじってました.でも今度は自分でもErlangプログラミングを始めようと思ったんで,

プログラミングErlang

プログラミングErlang

を買って勉強中です.今回はそのまとめ・・・

コードをロードする時の検索パスとその設定

Erlangから呼び出せるライブラリが配置されているpath一覧を出すコマンドは'code:get_path()'で,実際に実行してみると以下のように表示します.

% erl
Erlang (BEAM) emulator version 5.6.4 [source] [async-threads:0]
 [hipe] [kernel-poll:false]

Eshell V5.6.4  (abort with ^G)
1> code:get_path().
[".","/usr/local/lib/erlang/lib/kernel-2.12.4/ebin",
 "/usr/local/lib/erlang/lib/stdlib-1.15.4/ebin",
 "/usr/local/lib/erlang/lib/xmerl-1.1.10/ebin",
 "/usr/local/lib/erlang/lib/webtool-0.8.3.2/ebin",
 "/usr/local/lib/erlang/lib/typer-0.1.4/ebin",
 "/usr/local/lib/erlang/lib/tv-2.1.4.2/ebin",
 "/usr/local/lib/erlang/lib/tools-2.6.2/ebin",
 "/usr/local/lib/erlang/lib/toolbar-1.3.0.1/ebin",
 "/usr/local/lib/erlang/lib/test_server-3.2.3/ebin",
 "/usr/local/lib/erlang/lib/syntax_tools-1.5.5/ebin",
 "/usr/local/lib/erlang/lib/ssl-3.9/ebin",
 "/usr/local/lib/erlang/lib/ssh-1.0/ebin",
 "/usr/local/lib/erlang/lib/snmp-4.11.1/ebin",
 "/usr/local/lib/erlang/lib/sasl-2.1.5.3/ebin",
 "/usr/local/lib/erlang/lib/runtime_tools-1.7.2/ebin",
 "/usr/local/lib/erlang/lib/pman-2.6/ebin",
 "/usr/local/lib/erlang/lib/percept-0.7.2/ebin",
 "/usr/local/lib/erlang/lib/parsetools-1.4.5/ebin",
 "/usr/local/lib/erlang/lib/otp_mibs-1.0.4.1/ebin",
 "/usr/local/lib/erlang/lib/os_mon-2.1.7/ebin",
 "/usr/local/lib/erlang/lib/orber-3.6.9/ebin",
 "/usr/local/lib/erlang/lib/odbc-2.10.3/ebin",
 "/usr/local/lib/erlang/lib/observer-0.9.7.4/ebin",
 "/usr/local/lib/erlang/lib/mnesia-4.4.5/ebin",
 "/usr/local/lib/erlang/lib/megaco-3.8.1/ebin",
 "/usr/local/lib/erlang/lib/jinterface-1.4.1",
 "/usr/local/lib/erlang/lib/inviso-0.6/ebin",
 [...]|...]
2> 

リストの先頭にpathを加えるときが'code:add_pata("path")',末尾に加えるときは'code:add_pathz("path")',削除は'code:del_path()'になります.関連するマニュアルは'man code'で,そのdescriptionは以下のように始まります.

This module contains the interface to the Erlang code server, which deals with the loading of compiled code into a running Erlang runtime system.

マニュアルはman erlでもいいんですが,'erl -man erl'とコマンドするのが楽です.man initとかしても"BSD System Manager's Manual"がでてきますが,"erl -man init"ならErlangのinitについての説明が一発ででてきます.ちなみにunix系の場合マニュアル文書はプログラムとは別にインストールしておく必要があります.
これらパスの操作等起動時に毎回必要なコマンドは,ホームディレクトリの.erlangファイルに書いておくのが習慣なようですが,

$ erl -pa Dir1 -pa Dir2 ... -pz DirK1 -pz DirK2

と書く事もできます.コマンドを.erlangファイルに書く場合には以下のように記載します.

io:format("Running Erlang~n").
code:add_patha(".").
code:add_pathz("add_path_to_endoflist").

Erlangがホームディレクトリとして認識している場所は'init:get_argument(home)'でわかります.

プログラム起動

"Hello world"と出力するプログラムを実行することを考えてみます.まずプログラムをsample配下に作ってみます.

-module(hello).
-export([start/0]).

start() ->
    io:format("Hello World~n").

このプログラムを実行する最初の方法は,シェルでのコンパイルです.

% erl  
Erlang (BEAM) emulator version 5.6.4 [source] [async-threads:0]
 [hipe] [kernel-poll:false]

Running Erlang
config is in home/.erlang
Eshell V5.6.4  (abort with ^G)
1> cd("sample").
/Users/my/scratch/erl/sample
ok
2> c(hello).
{ok,hello}
3> hello:start().
Hello World
ok

次の方法はコマンドプロンプトからのコンパイルです.

% erlc hello.erl
Running Erlang
config is in home/.erlang
% erl -noshell -s hello start -s init stop
Running Erlang
config is in home/.erlang
Hello World
%

コマンドオプションの使い方は"erl -man erl"にあります.コマンドプロンプトから実行できるので,これをスクリプト化することもできます.こんな感じ.

#!/bin/sh
erl -noshell -s hello start -s init stop

実行時にはパスに注意する必要があります.指定したパスの中にプログラムがないと動きません.最後の方法はescriptを使う方法です.個人的にはこの方法が一番好きです.ただ,最近できるようになった方法らしくてちょっと前の解説にはescriptを使う方法はでていません.例えばhello.es(公式な拡張子ではありません)というスクリプトを作って

#!/usr/local/bin/escript
main(_) ->
    io:format("Hello world~n").

実行することになります.このスクリプトだと引数はないですが,引数を渡すとこんな感じになります.

#!/usr/local/bin/escript
main([A]) ->
  I = list_to_integer(A),
  F = fac(I),
  io:format("factorial ~w = ~w~n", [I, F]).

fac(0) ->1;
fac(N) ->
  N * fac(N-1).

プロセスを作るのに必要な時間

本に載ってるcode/processes.erlを動かしてみました.本だと,2.40GHz Intel Celeron,メモリ512MB,Ubuntu Linuxで,20,000個のプロセスを生成すると,1プロセスあたり1μsのCPU時間がかかり,経過時間が9.2μsとなってました.古いけど自前のiBookG4で試してみたらこんな感じ.

% erl
Erlang (BEAM) emulator version 5.6.4 [source] [async-threads:0]
 [hipe] [kernel-poll:false]

Running Erlang
config is in home/.erlang
Eshell V5.6.4  (abort with ^G)
1> processes:max(20000).
Maximum allowed processes:32768
Process spawn time=8.0 (15.25) microseconds
ok
2>

プロセスあたり8.0μsのCPU時間がかかり,見かけ上の経過時間は15.25μsかかってます.遅い…