ストリーム型通信でプログラマが知らなければいけないこと
基本は3つしかない。
これはバイナリだろうがテキストだろうが同じ。
・バッファリング
一回の受信ではデータが揃わないのでデータが解読できるまで貯めておくこと。
・ディスパッチ
データを解読してイベント処理を発行すること。
・イベント
イベント処理を受け取って必要な処理を行うこと。
■バッファリング
ストリーム型のデータには切れ目がない
だから送信時に切れ目を認識できるようにする
送信時には先頭にパケットデータサイズを入れておく
データが到着したらパケットデータサイズをまず確認して
自身が管理している受信可能最大値と比較して超えていたらドロップする
問題がなければパケットデータサイズ分データが貯まるまでバッファリングする
■ディスパッチ
3つの工程がある
・解析
パケットデータサイズ分のデータがたまったら解析処理を行う。
大抵がパケットサイズのあとに何を処理するかの種別データを埋め込んでおき
種別データを元にイベントを発行する。
・データ組立
なんのイベントかわかったらデータの組立処理を行う。
足りないデータなどがあればそれはおかしなパケット。
・イベント発行
イベント処理用の関数に組み立てたデータを入れて呼び出す。
■イベント
ここまで来たらなんの目的の処理かわかるので処理するだけ。
例:
パケットサイズ;イベント1;データ1;パケットサイズ;イベント2;データ2;パケットサイズ;イベント3;データ3;
nodejsで実行時にスクリプトファイルを読み込んで実行する
C++などでluaを使ってよくやるスクリプトシステムと同等の仕組みを意味があるか別としてやってみた。
new Functionを使うと簡単かつJITが効く速いコードができる。
逆にこういう用途に使うであろうvmモジュールはくっそ遅い上にunstableなので使いにくい
var fs = require('fs'); var txt = fs.readFileSync('./filevm.jss'); var MAX = 1000000; [function(){ var TID = 'newFunction'; var ctx = { hoge : 0, fuga : 0, }; var f = new Function('"use strict";'+txt); var x = f(); console.time(TID); try{ x.init(ctx); for(var i=0;i<MAX;++i){ x.update(ctx); } }catch(e){ console.log(e.stack); } console.timeEnd(TID); console.log(ctx.hoge); console.log(ctx.fuga); }].forEach(function(f){ f(); });
スクリプト側
function init(ctx){ ctx.hoge = 0; ctx.fuga = 0; } function update(ctx){ ctx.hoge+=1; if(ctx.hoge%2===0){ ctx.fuga+=1; } } return { init : init, update : update, };
100万回実行して13ms
newFunction: 13ms
js側で関数やオブジェクト作ってctxに突っ込んでスクリプト側で実行もできる。
この実装方法であればnode.jsを再起動(接続中のユーザーが切断されずに)しなくてもスクリプト部分だけ再読込して実行できる
東京node学園祭2012参加してきました
東京node学園祭2012参加してきました
イントロダクション
基調講演
New Readable Stream in Node 0.10
Nodeコアの歩き方
~Nodeの開発に参加しよう~
Running Node.js in Production
layering distributed systems
ECMAScript tools - composable modules and transpiler infrastructure
全体として自分は英語のリスニングができないので通訳が大変よかったと感じました。
ECMAScriptがWEBのアセンブラのような位置づけになりそうです。
LLVM、CLR、JVM、ECMAScriptサーバー/クライアント/OS問わず激しいシェア闘いがありそうな予感
あとで見てないセッションのUSTREAMの録画をみてみようとおもいます
Mikeal Rogersさんのやつがtweetみるとおもしろそうでした
http://www.ustream.tv/channel/nodefest2012a
node.jsのベンチマークいろいろ
githubにリポジトリ作った
https://github.com/you21979/nodejsbenchmark
・new Function
new Functionで動的にコード作るのたしかに早い。
evalはJIT効かないけどnew Functionは効いてる
requireが使えないけど。
・mysql + ayncblock
mysqlでasyncblock使った場合の速度低下を調べた
使った場合と使わない場合の比較
・redis + asyncblock
redisでasyncblock使った場合の速度低下を調べた
使った場合と使わない場合の比較
freenas8.3
freenas8.3が気づけば出てたのでついでにVMWARE-ESXiの仮想化ドライバも入れた
mount -o rw / mount -t cd9660 /dev/cd0 /media cd /tmp tar zxvf /media/vmware-freebsd-tools.tar.gz cd vmware-tools-distrib cp lib/modules/binary/FreeBSD8.1-amd64/*.ko /boot/modules vi /boot/loader.conf -------------------- vmxnet3_load="yes" -------------------- reboot
これで準仮想化のvmxnet3が使える
最適化2
前回の最適化で気になったので調べてみた
http://you21979.hateblo.jp/entry/2012/10/19/143845
nodejsでswitch ~ case遅いとあったけど実際に試してみて5000超えたあたりから許容できないかもしれない
20000のenumを作ってcaseしまくってるのだが
https://github.com/you21979/nodejsbenchmark/blob/master/v8/bigswitchcase.js
switch文の上の方ほどはやく下のほうが遅い。キャッチできなくでも下のほうと同様に遅い。
switch1: 0ms
switch2: 3ms
switch3: 30ms
switch4: 89ms
switch5: 69ms
関数テーブルで実装したほうが早い
https://github.com/you21979/nodejsbenchmark/blob/master/v8/bigfunctable.js
switch1: 0ms
switch2: 0ms
switch3: 0ms
switch4: 1ms
switch5: 0ms
中身ジャンプテーブルに展開されないんかなぁ。
手で書いたswitch文は気にしなくてもいいがDSLなどから自動生成したdispatcherを扱う場合には気をつけたほうがいいかも。
node.jsの0.8系
そろそろ使っても大丈夫そうだろうか
やばそうなバグもだいぶ取れてるっぽいし(メモリリークとか)
0.6系のアップデートが12月までだしなぁ
起動管理ツールでforeverが使えないとやっぱきついなぁと思っていたのだが
最近qilinもよさそうに感じてる