2012-02-11
■[haskell]GHCソースコードリーディング勉強会 第0回(準備編)に参加しました
http://partake.in/events/57179633-b2ad-4e7d-b56e-c4ac8e6b178e
リンク集がわりに
- GHC Commentary: The Compiler
http://hackage.haskell.org/trac/ghc/wiki/Commentary/Compiler
- Compiling one module: HscMain
http://hackage.haskell.org/trac/ghc/wiki/Commentary/Compiler/HscMain
- 岡部さんの資料
http://wiki.haskell.jp/Workshop/ReadGHC/0
http://d.hatena.ne.jp/suztomo/20111224/1324718354
- I know kung fu: learning STG by example http://hackage.haskell.org/trac/ghc/wiki/Commentary/Compiler/GeneratedCodeTracing
- the compilation of Hello Factorial!
http://blog.ezyang.com/2011/04/tracing-the-compilation-of-hello-factorial/
- Implementing lazy functional languages on stock hardware: the Spineless Tagless G-machine - Version 2.5 (1992)
http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.53.3729
- The Implementation of Functional Programming Languages http://research.microsoft.com/en-us/um/people/simonpj/papers/slpj-book-1987/
- Implementing functional languages: a tutorial http://research.microsoft.com/en-us/um/people/simonpj/papers/pj-lester-book/
- How to make a fast curry: push/enter vs eval/apply
http://research.microsoft.com/en-us/um/people/simonpj/papers/eval-apply/
- GHCのこと
http://www.kotha.net/hperf/ghc.html
Core言語の操作的解釈
http://www.haskell.org/ghc/docs/7.4.1/html/libraries/ghc-7.4.1/
2012-02-10 Yawsを埋め込む方法
この話は
http://yaws.hyber.org/embed.yaws
が元になっています。
管理画面などYawsで作成した場合に、本体のアプリケーションにYawsを埋め込みたい場合があると思います。
supervisorからyawsのプロセスを生成する方法を提供するためにAPIが提供されましたので、今回はそれ使ってyawsをアプリケーションに埋め込みます。
ポイントとなるのは
yaws_api:embedded_start_conf
という関数です。
この関数は設定ファイルを使わず、リストから設定を行い、
・SconfList
設定
・GC
f() -> Id = ?ID, GconfList = [{id,Id}], DocRoot = DocRoot, SconfList = [{port, Port}, {servername, ServerName}, {listen, Host}, {docroot , DocRoot}, {appmods, [{"/", ?APP_MOD, [["js"], ["top", "static"], ["icons"]]}]} ], {ok, SCList, GC, ChildSpecs} = yaws_api:embedded_start_conf(DocRoot, SconfList, GconfList, Id), [supervisor:start_child(?SUPER, Ch) || Ch <- ChildSpecs], yaws_api:embedded_start_conf(GC, SCList), {ok, self()}.
上で出てくるappmodsとはapplication modulesのことです。
http://yaws.hyber.org/appmods.yaws
- super_visor
init(Args) -> io:format("args=~p~n",[Args]), [{Host, Port, ServerName, DocRoot}] = Args, YBed = {?CHILD, {?CHILD, start, [Host, Port, ServerName, DocRoot]}, permanent, 2000, worker, [?CHILD]}, {ok, {{one_for_all, 0, 1}, [YBed]}}.
■[Erlang]でSSL
ErlangでSSLで詰まった箇所があるのですが、その時のメモをまとめました。
- configure
configure --with-ssl
などしてconfigureオプションを与える必要があります
- 設定ファル
certificateとkeyファイルが必要です
opensslなどで作成しておきましょう。
opensslの使い方はこちらを参考にしてください
http://pdincau.wordpress.com/2011/06/22/a-brief-introduction-to-ssl-with-erlang/
openssl genrsa -out key.pem 1024
でkey.pemを作成します。
certificate.pem
を作成するために
request.pem
を作成する必要があります
openssl req -new -key key.pem -out request.pem
$ openssl x509 -req -days 30 -in request.pem -signkey key.pem -out certificate.pem
作成したファイルをサーバ側で設定する必要があります。
listen時に設定する。
- 通信設定
ちなみに
{active, false}を設定しておかないと通信が受け取れません。
したの例では、ssl:listenでlisten時に設定しています。
- server側
{ok, ListenSocket} = ssl:listen(Port,
[{certfile, CertFile},
{keyfile, KeyFile},
{reuseaddr, false},
{ssl_imp, new},
{nodelay, true},
{depth, 3},
{active, false}
]),
certfile、keyfileにそれぞれ、先程作成したファイルのパスを指定してあげます。
同様にクライアント側でも、通信の設定を行う必要があります。
{ok, Socket} =
ssl:connect(?HOST, ?PORT, [{nodelay, true},{ssl_imp, new},{active, false}], infinity),
{active, false}
- タプルを送受信するためには
じつはssl(というかtcp)はsend()を使ってタプルをそのまま送信することが出来ません。
- 送信側
ok = ssl:send(Socket,term_to_binary(Data)),
term_to_binaryでタプルをバイナリに変換します。
- 受信側
{ok,Data} = ssl:recv(Socket,0),
binary_to_term(list_to_binary(Data)),
binary_to_term . list_to_binary
■[Erlang] QuickCheckでテストファイル自動生成
- 取得
- ライブラリ
起動時にebinにパスを設定必要があります。
- 自動生成
ErlangQuickCheckは
1.自動生成、
2.それ入力にとり対象テストコードを実行、
3.結果を元にチェック
という3つのフェーズで行われます。
ここでファイルを自動生成するために
2.でテストコードを実行する代わりに生成コードを実行させるようにします。
3.に必ず成功するコードたとえば1==1のような式を与えます。
-include_lib("eqc.hrl"). word() -> list(oneof(seq($A,$F) ++ seq($a,$f) ++ seq($0, $9))). test() -> ?FORALL({XS},{word()}, begin {ok,Path} = file:get_cwd(), {ok,IoDevice} = file:opne(filenaem), io:format(IoDevice "~s",[XS]), XS=XS end).
2012-01-27
■[Haskell] Conduitのトリビアルでシンプルなサンプル
Haskellの新しいIOライブラリのトリビアルなサンプルを書きました。
Conduitとは、水道管とか溝とか言う意味です。
この例は読み込みと書き込みのファイルを開いて10文字だけコピーするだけのサンプルです
do構文で組み立てられたResourceTモナドをrunResourceで実行とモナド変換を行います
このdo構文の中は大まかに分けて3つとなります。
リーソスの確保
(srcKey, rHandle) <- with (openFile src $ ReadMode) $ hClose
withを使ってリソースを確保します。
それぞれコンストラクタとデストラクタのようなものです。
withの返り値はタプルとなっています。このタプルの一番目がキーとなっており開放のために使います。二番目はハンドルとなっており、パイプ処理の時にSource,Sinkに変換して使います。
with定義
withSource :: Resource m => Base m aallocate -> (a -> Base m ())free resource -> ResourceT m (ReleaseKey, a)
パイプ処理
ResourceTを組み立てる必要があります。
そのために
source -> conduit -> sink
(unixの例えでばよけばcoduitはパイプ"|")
というパイプを作り必要があります。
この例の場合
(sourceHandle rHandle) $= (isolate 10) $$ sinkHandle wHandle
該当箇所となります。
- source
sourceHandle rHandle
sourceHandle定義
sourceHandle :: ResourceIO m => Handle -> Source m ByteString
- conduit
(isolate 10)
- sink
sinkHandle wHandle
sinkHandle定義
sinkHandle :: ResourceIO m => Handle -> Sink ByteString m ()
となります
sourceHandle, sinkHandleはそれぞれハンドルをsource、sinkに変換する関数です。
こうして作られたパイプコンビネータ($$)ResourceT組み立てます。
isolate定義
isolate :: Resource m => Int -> Conduit ByteString m ByteString
($$) 定義
($$) :: (IsSource src, Resource m) => src m a -> Sink a m b -> ResourceT m b
($=)定義
($=) :: (IsSource src, Resource m) => src m a -> Conduit a m b -> Source m b
リソース開放
release srcKey
release定義
release :: Resource m => ReleaseKey -> ResourceT m ()
2011-12-24 Erlangのソースコードを読むためにその一

ErlangのBeam/Emulatorを読むために、valgrindをつかってコールトレースを表示する方法を紹介します。
configureとビルド
config時に
./configure --disable-hipe
とする必要があります。
これをしないvalgrindオプション付きのVMをビルドする際に、
リンク時にシンボルが解決されずビルドに失敗してしまいます。
hipeというは、Erlangの最適化の一種で、コンパイル後のコードの一部をbyteコードではなくネイティブコードとしてコンパイルしてVMから呼び出す手法のようです。
この中で、valgrindオプション付きのVMは浮動小数点系のシンボルが解決できないようです。(otp R14B04)
make
cd erts/emulator make valgrind
実行
次にbin/cerlを修正します。
#exec valgrind $valgrind_xml $valgrind_log $valgrind_misc_flags $BINDIR/$EMU_NAME $emu_xargs $early_beam_args "$PROGNAME" $late_beam_args -pz $PRELOADED exec valgrind "--trace-children=yes" "--child-silent-after-fork=no" "--tool=callgrind" $valgrind_xml $valgrind_log $valgrind_misc_flags $BINDIR/$EMU_NAME $emu_xargs $early_beam_args "$PROGNAME" $late_beam_args -pz $PRELOADED
これはvalgrindに対してオプションを渡すためにやっています。
bin/cerl -valgrind
とすると
callgrind.out.47836
みたいなファイルができていると思います。これがvalgrindの出力したファイルです。
コールツリー出力
このままでもいいんですが、コールとレースを見たいので次のコマンドを発行してコールグラフを出力します。
callgrind_annotate -I=../erts/emulator/beam,../erts/emulator/sys/unix --tree=both ./callgrind.out.47836
すこしcallgrind_annotateオプションの説明をすると
-Iオプションはソースの場所を指定しています。
-tree=bothはコールツリーを表示し呼び出し元と先を表示するという意味です。

