針の上でprocessは幾つ踊れるか? このページをアンテナに追加 RSSフィード

2012-02-11

[]GHCソースコードリーディング勉強会 第0回(準備編)に参加しました

GHCソースコードリーディング勉強会 第0回(準備編)

http://partake.in/events/57179633-b2ad-4e7d-b56e-c4ac8e6b178e

リンク集がわりに

http://togetter.com/li/256046

  • 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

  • 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

http://public.iwork.com/document/ja/?a=p50720299&d=GHC%E5%8B%89%E5%BC%B7%E4%BC%9A%E7%AC%AC0%E5%9B%9E.key

  • How to make a fast curry: push/enter vs eval/apply

http://research.microsoft.com/en-us/um/people/simonpj/papers/eval-apply/


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]}}.

[]でSSL

ErlangSSLで詰まった箇所があるのですが、その時のメモをまとめました。

  • configure

Erlang

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

ssl:connectの第三引数

{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

という2つの関数でDataのバイナリをタプルへと変換しています。

[] 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

[] Conduitのトリビアルでシンプルなサンプル

Haskellの新しいIOライブラリトリビアルなサンプルを書きました。

Conduitとは、水道管とか溝とか言う意味です。

この例は読み込みと書き込みのファイルを開いて10文字だけコピーするだけのサンプルです

do構文で組み立てられたResourceTモナドをrunResourceで実行とモナド変換を行います

このdo構文の中は大まかに分けて3つとなります。


リーソスの確保

(srcKey, rHandle) <- with (openFile src $ ReadMode) $ hClose 

withを使ってリソースを確保します。

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に変換する関数です。

($=)演算子はConduitを結合するための演算子です。

こうして作られたパイプコンビネータ($$)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関数を使って行われます

release srcKey
release定義
release :: Resource m => ReleaseKey -> ResourceT m ()

2011-12-24 Erlangのソースコードを読むためにその一 このエントリーを含むブックマーク このエントリーのブックマークコメント

Erlangソースコードを読むためにその一

ErlangのBeam/Emulatorを読むために、valgrindをつかってコールトレースを表示する方法を紹介します。

configureとビルド

config時に

./configure --disable-hipe

とする必要があります。

これをしないvalgrindオプション付きのVMビルドする際に、

リンク時にシンボルが解決されずビルドに失敗してしまいます。

hipeというは、Erlang最適化の一種で、コンパイル後のコードの一部をbyteコードではなくネイティブコードとしてコンパイルしてVMから呼び出す手法のようです。

この中で、valgrindオプション付きのVM浮動小数点系のシンボルが解決できないようです。(otp R14B04)

make

し、あとはvalgrindつきのVMビルドします。

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はコールツリーを表示し呼び出し元と先を表示するという意味です。

2011-08-02

[][]

1 {dup 100 ge {exit} {dup 5 mod 0 eq {(Buzz) exch} if dup 3 mod 0 eq {(Fizz)  exch} if dup 1 add}  ifelse} loop pstack

github

githubのソースがのっけられるかテスト