2012年03月30日

Bashoのrebar、いいね

BashoのrebarというErlang用ビルドツール(?)を使い始めて3週間ほどたったのですが、ようやく「複数階層」「複数スーパバイザ」という今回のSimple dungeonの構成を模したソースツリーが構築できました。

simpledungeon-tree-20120330.png


なんというか、この感謝を言葉にするのがすごく難しい。rebarを作って公開してくれたBashoのみなさん、あと、サイトでrebarを紹介されてたVoluntasさんにも。


rebar入れてから「とりあえず使えるようになりました」と言えるまで3週間も時間がかかったのは、今まで、まじめにOTPを使ってこなかったのが原因です。ずっとErlangとしてしか使ってなかった。OTPじゃなかった。rebarはもう初日からバリバリとテンプレートコードを生成してくれてたのに、もうほんと申し訳ないって感じ。rebarが吐き出してくれるコードが意味わかんない状態だったからもうw


ただ、rebarのありがたみというかOTPの有り難みは、「自作loopでメッセージを何とかこなすのが精一杯の、それでも目的の動作はしてくれる初期構築コード」を経たからなのかもしれない。それでも4年はかけ過ぎだけどww (今確認したら、アマゾンから飛行機本を買ったのが2008年3月21日。うは。まじ4年)


今、とりあえず、OTPベースのプロセス監視ツリーをきちんと構築したsimpledungeonにリフレッシュ作業中です。そこまでできたら、コードの動的入れ替えやら、いろんなことが可能になって、ちゃんと「リリースしました」といえる気がする。今はまだ「落ちたらごめんなさいサンプル」だ。それではオンラインゲームのサーバーとしては「実証段階」だし、そんなレベルじゃ誰も使わない(私も使わない)。


というわけで、落ちないsimpledungeonに向けて、コードの書き換え中。rebarベースに移植が完了したら、commitしてまたご報告します。

とにかく感謝の気持ちがいっぱいなので、とりあえずエントリ書きました。

ありがとーーー!
posted by へろ at 00:52| Comment(0) | TrackBack(0) | Erlang

2012年03月11日

Windowsでrebarを使う

ふだんの開発をWindowsで行っているのですが、ErlangのビルドツールとしてVoluntasさんがこちらの記事で推奨してた、rebar (githubはこちらzipはこちら)を入れてみることにしました。

Windows固有のハマリが2つ。

・nmakeでmakeできない。
・self containing escriptになってるのを動かそうとしたら、escriptが下のようなメッセージを出してrebarを実行してくれない
C:\HOGEHOGE>escript rebar
escript: Failed to open file: C:\HOGEHOGE\escript.escript



というわけで、それぞれのとりあえずの解決。


・nmakeでmakeできない。

本体のビルド作業だけなら bootstrap.bat を実行すればよいので、makeではなく
C:\rebar> bootstrap.bat

のようにすればOKです。

・escriptがエラーを出してrebarを実行してくれない

上の手順でビルドして作られた「rebar」ファイルだけを持ってくれば動くはずなのですが、今度はescriptがうまく動かない。。。

解決してしまえばシンプルでした。

動かない > C:\HOGEHOGE> escript rebar


動く!  > C:\HOGEHOGE> escript.exe rebar


Franco Lombardoさんのこちらのエントリ(英語)にあるように、escriptを"escript.exe" として起動してあげないと、引数のファイルを読みに行ってくれないようです。

escriptのソースは読んでませんが、argv[0]が自分のファイル名(escript.exe)でない場合は、escript.exeが「argv[1]ではなく、argv[0]が実行すべきescriptファイルだ」と判断して、argv[0]そのもの、もしくはargv[0]に".escript"を付加したファイルを探しに行く、という動作になっているものと思われます。これ自体は妥当な動きなので「escript.exe」で実行するようにすればいいだけですね。

というわけで、

C:\> copy \rebar\rebar \HOGEHOGE
C:\> cd \HOGEHOGE
C:\> escript.exe rebar


という流れで、Windowsでもrebarの準備ができました^^


※補足

ビルドされたrebarファイルですが、Windowsで作ってもLinuxで作っても同じようにUnixのスクリプトファイル形式(#!で始まるあれ)で出力されます。というわけで、Erlangのバージョンが同じならLinux環境でビルドしたものをそのまま使うことも可能ですね。
posted by へろ at 11:19| Comment(1) | TrackBack(0) | Erlang

2012年03月09日

Rev277でGreenに戻りました>Simple dungeon

開発中のMMO作成支援サービス「Simple dungeon」で、trunkのツリーでテストエラーが発生していたのですが、テストが通るようプログラムとテストデータを修正。


Simple dungeonのJenkins画面


simpledungeon-rev277-jp.png

Stableに戻りました。

テストが2つ減っていますが、これは古いコードで残っていたテストを、古いコードごと削除したことによるものです。
posted by へろ at 23:41| Comment(0) | TrackBack(0) | 日記

Simple dungeon、ふたたびunstable状態です(Rev276

開発中のMMO作成支援サービス「Simple dungeon」で、trunkのツリーでテストエラーが発生中です。

Simple dungeonのJenkins画面

ここ2ヶ月の修正で内部構造をいじった時に、内部的にIDを数値で持たせようとしていたのですが、それだと一部クライアントが動かない現象が発生するため、方針を再度あらため、旧構造のように文字列(erlang的にはリスト)として扱うように変更することにしました。

これに向けて先行してテストを変更したため、エラーが出始めたものです。

現在、本体の方の修正を行っています。
posted by へろ at 11:13| Comment(0) | TrackBack(0) | 日記

2012年03月06日

Simple dungeonのビルドがGreenに戻りました

というわけで、開発中のサーバー側ソフトSimple dungeonのビルドがGreenに戻りました。

Jenkinsのページはこちら

jenkins-goes-back-green-rev266.png

マルチテナント化するために直し壊ししてましたが、ようやくスタート地点まで押し戻したという感じです。

リファクタリングとかはこれからですが、なんとか開発を加速していきたいですね。
posted by へろ at 00:07| Comment(0) | TrackBack(0) | Erlang

2012年02月29日

Simple dungeon Rev.252、エラー中です

開発中のMMO作成支援サービス「Simple dungeon」で、trunkのツリーにエラーが発生中です。

Simple dungeonのJenkins画面

branch側で試していた新しい構成を、先週からtrunkに統合しているのですが、一部モジュール名やデータの持ち方を変えようとしているためエラーが出ています。

モジュール名を変えたり、ユーティリティ関数を別モジュールに移したりという変更もしているので、テストが通らないだけでなく、動作にも支障があります。

現在、修正中です。


補足。チェックインしなければいいのに? おっしゃるとおりです。。。
posted by へろ at 13:01| Comment(0) | TrackBack(0) | Erlang

2012年02月25日

gen_server内のハンドルでio:formatで出力するとエラーになる

作成中のSimpledungeon、Erlang実行環境ををErlang/OTP R15Bにアップしたところ、R13B04でノーエラー状態だったはずのtrunkのコードがテストでエラー出まくりになっていました。

で、ずっと追っかけてたのですが、どうやらgen_server内のハンドルでio:formatで出力するとエラーになるように修正が加えられたようです(リリースノートの追跡は後でやります(やらないフラグ))

というわけで、各所を修正しました。

sourceforgeに置いたsimple dungeon はこちら



posted by へろ at 15:24| Comment(0) | TrackBack(0) | Erlang

2012年01月09日

cryptoのベンチマークを追試した

ゆうべ、cryptoがボトルネックになりうるかどうかを計測してみましたが、今朝起きて「さすがにバラつきすぎだろう」と思い、同じコードをLinuxにもっていって計測し直してみました。

同じマシンで、Windows版VirtualboxでCentOS6.2 32bit版を動かしています。

10回計測、単位は秒。

1万プロセス10万プロセス
暗号なし暗号あり暗号なし暗号あり
平均0.1050.1137.7307.806
最大0.1890.2167.8527.886
最小0.0930.0987.6947.789


というわけで、ばらつきが減って、cryptoの負荷がどれくらいかが見えやすくなりましたね。

cryptoへ一気に流し込んでも、それほど処理の影響はなさそうです。
そもそもcryptoの処理自体が(全体と比して)軽そうです。


とした結論のところは変わりません。
posted by へろ at 11:46| Comment(4) | TrackBack(0) | Erlang

cryptoの処理能力を試してみた>想定用途には余裕っぽい

というわけで、暗号化ライブラリ「crypto」の使いどころのエントリで、voluntasさんから秒間数千程度なら「気にせず使っても問題ありませんよ」とのコメントをいただいてたので、ちょっとコードを書いて試してみました。

Windows7 64ビット版
Erlang OTP R15B(x64)
CPU AMD PhenomII X4 905e 2.5GHz
メモリ 12GB

という環境で、erl.exeにて実行。10回の計測を実施、単位は秒。

1万プロセス10万プロセス
暗号なし暗号あり暗号なし暗号あり
平均0.3040.27838.28640.150
最大0.4990.500104.365117.983
最小0.1560.15610.45210.936


でした。割とばらつくのはWindows上のVMだからでしょうか。1万プロセス〜10万プロセスぐらいだと最大も最小もほぼ変わらないですね。cryptoへ一気に流し込んでも、それほど処理の影響はなさそうです。
そもそもcryptoの処理自体が(全体と比して)軽そうです。

crypto処理ありのベンチマークテストコード。

-module(cryptobench).
-import(lists, [foreach/2]).

-compile(export_all).

start(A) ->
crypto:start(),
E = encrypt_text("Hello World!"),
L = lists:seq(1, A, 1),
SendBackPid = self(),
StartTime = erlang:now(),
lists:map(fun(X) -> spawn(fun() -> sendback(SendBackPid, X, E) end) end ,L),
loop([], A),
EndTime = erlang:now(),
Diff = timer:now_diff( EndTime, StartTime ),
io:format("elapsed time: ~p (sec)~n", [ Diff / 1000000 ]),
crypto:stop().

loop(State, Count) when length(State) == Count ->
io:format("end of loop~p~n", [length(State)]);

loop(State, Count) ->
receive
{hello, Id, "Hello World!", _SenderPid} -> loop([Id | State], Count);
_ -> loop(State, Count)
end.

sendback(To, Id, E) ->
To ! {hello, Id, decrypt_text(E), self()}.

%% Encryption utilities.

encryption_key() -> <<16#01,16#23,16#45,16#67,16#89,16#AB,16#CD,16#EF,16#F0,16#12,16#34,16#56,16#78,16#9A,16#BC,16#DE>>.
encryption_iv() -> <<16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00,16#00>>.

encrypt_text(PlainText) ->
encrypt_bin(erlang:list_to_binary(PlainText)).

encrypt_bin(Binary) ->
Key = encryption_key(),
IVec = crypto:aes_cbc_ivec(encryption_iv()),
crypto:aes_ctr_encrypt(Key, IVec, Binary).

decrypt_text(Encrypted) ->
erlang:binary_to_list(decrypt_bin(Encrypted)).

decrypt_bin(Encrypted) ->
Key = encryption_key(),
IVec = crypto:aes_cbc_ivec(encryption_iv()),
crypto:aes_ctr_decrypt(Key, IVec, Encrypted).


こちらがcrypto処理無しの方。

-module(bench).
-import(lists, [foreach/2]).

-compile(export_all).

start(A) ->
E = "Hello World!",
L = lists:seq(1, A, 1),
SendBackPid = self(),
StartTime = erlang:now(),
lists:map(fun(X) -> spawn(fun() -> sendback(SendBackPid, X, E) end) end ,L),
loop([], A),
EndTime = erlang:now(),
Diff = timer:now_diff( EndTime, StartTime ),
io:format("elapsed time: ~p (sec)~n", [ Diff / 1000000 ]).

loop(State, Count) when length(State) == Count ->
io:format("end of loop~p~n", [length(State)]);

loop(State, Count) ->
receive
{hello, Id, "Hello World!", _SenderPid} -> loop([Id | State], Count);
_ -> loop(State, Count)
end.

sendback(To, Id, E) ->
To ! {hello, Id, E, self()}.

posted by へろ at 00:15| Comment(2) | TrackBack(0) | Erlang

2012年01月07日

mnesia:transaction/1から、mnesia:activity/2への変更

mnesia:transaction/1について、いろいろ書いてたところ、voluntas さんから「mnesia:transaction/1 ではなく mnesia:activity/2 を使うといいですよ。」とのアドバイスをいただいた。

mnesia:activity/2は飛行機本で紹介されてなかったこともあり、まったく知らなかったので、ドキュメントとかvoluntasさんの書かれたソースとか見てみた。とりあえず、mnesia:transaction/1に近い使い方をしたいだけなら、ちょっと書き換えるだけで使えそうな気配。具体的にはこんな感じ。

1> mnesia:transaction(fun() -> mnesia:read({sample, foo}) end).
{atomic,[{sample, foo, data_of_foo}]}

2> mnesia:activity(transaction, fun() -> mnesia:read({sample, foo}) end).
[{sample, foo, data_of_foo}]


mnesia:activity/2にするときは、
・第1引数に「transaction」を指定する。
・返ってくる値は「 {atomic, VALUE} 」ではなく、「 VALUE 」となる。
の2点でなんとかなりそう。

トランザクション以外の処理させ方もいろいろ使えるみたい。ドキュメントはこちら>mnesia:activity/2

ちなみに、存在しないテーブル名を指定するなどして失敗すると、mnesia:transaction/1だったら{aborted, Reason}だったのが、mnesia:activity/2だと、いきなりexitしてくるんですね。気をつけます。
posted by へろ at 19:57| Comment(0) | TrackBack(0) | Erlang