you21979の日記

実験ネタとか。仮想化とかnodejsで嵌った所とかおもしろかったところとかいろいろ

ストリーム型通信でプログラマが知らなければいけないこと

基本は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

 

全体として自分は英語のリスニングができないので通訳が大変よかったと感じました。

基調講演ではnode.js 1.0はもう少し先で0.10がもうすぐ出るとのこと。
自分は0.6をようやくアップデートして0.8を使うことにしたばかりなので
はやいなぁと。
package.jsonで依存関係ちゃんとやっとかないとまた動かなくなるのが出そう。
(NPMはnodeのバージョン関係なく最新版とってきてしまうので)
 
nodeコアの歩き方はドキュメントには書いてないnodeの仕組みでどこからみていったらよいかのとっかかりを紹介しいてた
自分もC++のソースは読んでいるがまだ全部把握してるわけじゃないので参考になった
大津さんの講演は前回のprocess.nextTickも大変参考になったし当分ウォッチさせていただこうと思っている。
 
Running Node.js in Productionはjitsuのceoの人でした
プロダクションレベルで運用するノウハウを講演してました
メモリリークは僕が前に書いたようにイベントリスナーには気をつけろとのことでした
npmのレプリケーションでプライベートnpmについても話していました
 
layering distributed systemsはsubstackの人で達人級の人が持ってる哲学をやってそうな人でした。
ストリームのプログラムをライブプログラミングでやってたのがとても印象的。
ゴシッププロトコルのところでチラチラ動かしてたMMOみたいなゲーム画面はどうなったんだろう
 
ECMAScript Toolsは自分も少し触ってみようかと思ったくらい面白そうでした

 

ECMAScriptがWEBのアセンブラのような位置づけになりそうです。

LLVM、CLRJVMECMAScriptサーバー/クライアント/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もよさそうに感じてる