OCatraをLwt使うようにした
OCatraをいろいろ直したり、ベンチマークとってみたり - komamitsu.log で作っていたOCamlのおもちゃ的Webサーバー OCatraをLwtを使うように修正してみた。
1st | 2nd | 3rd | 4th | Ave. | |
---|---|---|---|---|---|
OCatra (byte) | 4238 | 4424 | 4299 | 4285 | 4311 |
OCatra (opt) | 11806 | 12384 | 12381 | 12063 | 12158 |
bytecode版で1.5倍程度、native版で3倍程度高速になってうれしい。
nginxもついでに測ってみたのだけど、nginxのほうが倍近く速くて悔しい...
OPAMでインストールしたパッケージがocamlfindで見つからない件
OPAMいいですね。
http://d.hatena.ne.jp/wistery_k/20120909/1347164530 の記事を見て使い始めましたが、道具としてのOCamlが何かの壁を乗り越えそうな感じがしてます。
で、使っていて、たまにocamlfind -listの中にopamでインストールしたパッケージが出てこないことに気がつきました。
eval `opam config -env` でパス周りの設定を通しているので、こいつは .xxshrc辺りに書いておいてあげる必要がありそうです。
あと本題と関係ないけど、shell/opam_completion.sh とかを読み込んでおくと auto-completeが効くのでさらに便利。
追記(2012-10-08)
https://github.com/OCamlPro/opam に普通に載ってたわ...
OCatraをいろいろ直したり、ベンチマークとってみたり
komamitsu/OCatra · GitHub のkeepaliveまわりのバグとかを直したり、モジュール名を変更したりしました。
Eventモジュールを使ってすっきり書いた方が良さげだなぁとか思っているのですが、現状そんなにややこしい制御をしていないので、まぁいいかと。
あとついでに、thin上でSinatraを動かしたやつと、abでrpsを比べてみました (-c 200 -n 4000)。
1st | 2nd | 3rd | 4th | Ave. | σ | |
---|---|---|---|---|---|---|
OCatra (byte) | 3089 | 3197 | 1761 | 3415 | 2865 | 748 |
OCatra (opt) | 4288 | 1809 | 6120 | 3920 | 4036 | 1768 |
Sinatra + thin | 1561 | 1613 | 1595 | 1557 | 1581 | 27 |
bytecode版とnative版でともにSinatra + thinよりも速いのですが、測定値にばらつきがありました。99%のリクエストは一瞬なんですが、1%未満でレスポンスが遅くなるみたい。ちょっと気になるな〜
OCatraを短くかけるように修正
SinatraっぽいOCatraを書いてみた - komamitsu.log で作ったOCatraですが、もうちょっとすっきり書けるように修正。
open Ocatra open HttpCommon open HttpCommon.HttpContent let _ = get "/" (fun r -> say (TextPlain "Hello, World (GET)") ()); post "/" (fun r -> say (TextPlain "Hello, World (POST)") ()); get "/givemeyournameandage" (fun r -> say ( TextHtml ( "<html><head><title>hello " ^ r ++> "name" ^ "</title></head>" ^ "<body><h3>you are " ^ r ++> "age" ^ " years old.</h3></body></html>") ) () ); run ()
SinatraっぽいOCatraを書いてみた
先日、やっつけのWebサーバーを書く際にRubyのSinatraで書いてみたのですが、「簡単に書けて良いな〜」と思ったので、OCamlでもそれっぽいものを適当に作ってみました。
現状はこんな感じでかけます:
open Ocatra open HttpCommon open HttpRequest open HttpResponse let _ = get "/" (fun req -> create_response (Some (HttpContent.TextPlain "Hello, World (GET)")) () ); post "/" (fun req -> create_response (Some (HttpContent.TextPlain "Hello, World (POST)")) () ); get "/givemeyournameandage" (fun req -> let name = HttpParam.find req.param "name" in let age = HttpParam.find req.param "age" in create_response (Some ( HttpContent.TextHtml ( "<html><head><title>hello " ^ name ^ "</title></head>" ^ "<body><h3>you are " ^ age ^ " years old.</h3></body></html>") )) () ); run ()
「それっぽい感じで書けそうかな?」というのを確認した段階なので、肝心の「短くかけるか?」というのはあまり追求してない... 後で暇になったら頑張ろうかなと。
あと、ソースコードの配置とかMakefileとかSignature切ってないとかが、やっつけ感溢れるというか適当なので、これも暇になったら頑張りたい。
あと、OCamlのライブラリ依存を何とかするのが面倒で苦手なので、品質よりも簡単に使えること(できるだけ標準で用意されている環境で使いたい)優先で、HTTPサーバー的なところは自前で実装しています。この辺も結構適当にやってるので暇になったら頑張りたい。
パーセプトロンの練習
最近、機械学習に興味を持ち始めていて、SVMを実装してみようと思ったら、挫折したのでやはり段階を踏むべきであろうということでパーセプトロンから試してみた。
komamitsu/ocaml-perceptron · GitHub
- perceptron.ml
let ($) f g = f g let print x = Hashtbl.iter (fun k v -> Printf.printf "%s => %d " k v) x; print_newline () let inner_prod w x = Hashtbl.fold (fun wk wv a -> a + wv * (Hashtbl.find x wk)) w 0 let classify w x = if inner_prod w x >= 0 then 1 else -1 let learn w x y = if classify w x != y then Hashtbl.iter (fun xk xv -> let wv = Hashtbl.find w xk in Hashtbl.replace w xk $ wv + xv * y) x let learn_all n w set_of_x_y = for i = 1 to n do List.iter (fun (x, y) -> learn w x y) set_of_x_y done; w
これがパーセプトロンで学習したり分類したりするもので、何というか手順をそのままコードに落としただけ。
- sample.ml
(* * ocamlc -c perceptron.ml && ocaml perceptron.cmo sample.ml *) let ($) f g = f g let vec_of_assoc assoc = List.fold_left (fun w (k, v) -> Hashtbl.replace w k v; w) (Hashtbl.create 4) assoc let train_src = List.rev $ List.fold_left (fun train_src (assoc, y) -> let x = vec_of_assoc assoc in (x, y)::train_src) [] [ ([("R", 255); ("G", 0); ("B", 0); ("bias", 1)], 1); ([("R", 0); ("G", 255); ("B", 255); ("bias", 1)], -1); ([("R", 0); ("G", 255); ("B", 0); ("bias", 1)], -1); ([("R", 255); ("G", 0); ("B", 255); ("bias", 1)], 1); ([("R", 0); ("G", 0); ("B", 255); ("bias", 1)], -1); ([("R", 255); ("G", 255); ("B", 0); ("bias", 1)], 1); ] let print_result x = let s = if x = 1 then "warm" else "cool" in print_endline s let _ = let init = vec_of_assoc [("R", 0); ("G", 0); ("B", 0); ("bias", 1)] in let w = Perceptron.learn_all 10 init train_src in Perceptron.print w; let x = vec_of_assoc [("R", 200); ("G", 100); ("B", 100); ("bias", 1)] in print_result $ Perceptron.classify w x; let x = vec_of_assoc [("R", 100); ("G", 200); ("B", 200); ("bias", 1)] in print_result $ Perceptron.classify w x
で、こちらがそれを利用するサンプルで、機械学習超入門III 〜機械学習の基礎、パーセプトロンを30分で作って学ぶ〜 - EchizenBlog-Zweiの暖色・寒色の例を使わせて頂きました。
実行するとこんな感じに。
komamitsu@carrot:~/lab/ocaml/perceptron$ ocamlc -c perceptron.ml && ocaml perceptron.cmo sample.ml bias => 0 B => -255 R => 255 G => -255 warm cool
それはそうと、OCamlでHashtblを簡単に構築できるリテラル(PerlとかRubyみたいやつ)が欲しいなぁと思いました。camlp4を使った何かがあるのかなぁ。