2013年7月28日日曜日

久しぶりのSecondLife!乗り物のSIM越え遅延原因を検証する



今回は久しぶりのSecondLifeで、乗り物でSIMを越える時の引っかかりについて検証します。



コレ結構致命的なレベルで発生していて、SIM越えの度に5秒とか10秒固まるケースもあります。

SIM越えの際にSIM側で何が起きているのかをちゃんと調べるのが正攻法だと思いますが、正直良く分かりません。メモリの確保やらなんやらあるんでしょうね。

まぁ細かいところは良く分からないので、取りあえず色々と実験してみます。


まずは基準としてx:2m y:2mにリサイズしたキューブを用意し、これに飛行機のスクリプトを突っ込みます。



こいつのサイズを変えたりプリム数を変えたり、色々なスクリプトを放り込んだりしながら、SIM境界を20回ぐらい行ったり来たりして、遅延の平均を取ります。

遅延の計測方法はllGetTimestamp()を使ってミリ秒単位で計測します。


■基準

 平均遅延:268ms


このぐらいだと少し引っかかるなぁぐらいで特に問題ありません。


■プリムサイズによる差異

・基準のプリムサイズをx:30m y:30mにリサイズ。

 平均遅延:275ms


 サイズを変えてもあまり変わらないようです。


■プリム数による差異

・基準のプリムを30リンクさせたオブジェクトを利用。

 平均遅延:1,000ms


一気に悪化します。


■スクリプトの量による差異

・基準にVICE関連のスクリプトを投入。

 平均遅延:998ms


リンクされたプリム数が30の場合と同じぐらい悪化します。


・30プリムのオブジェクトにVICE関連のスクリプトを投入。

 平均遅延:1,548ms


当然さらに悪化します。


■スクリプトのファイル数による差異

・基準に300個の変数を定義したスクリプトファイルを投入。

 平均遅延:448ms

・基準に30個の変数を定義したスクリプトファイルを10ファイル投入。

 平均遅延:744ms


ファイル数が増えると悪化するようです。



ということで、最後のファイル数の部分以外は、何が悪影響というよりは基本的には足し算で、何か実装すればそれだけ遅延が発生するという印象です。

結論としては、何でもかんでも実装するのではなく必要な機能を絞ることと、最適化のためにファイル数を最小にするというところでしょうか。

まぁサンプル数も少なく、SIM側のトラフィックなどの影響もあるでしょうし、どこまで正しいか分かりませんが、なんとなく遅延を減らすには何をすべきかは見えた気がします。

Read More...

2013年7月8日月曜日

最寄り駅を教えろ!Google Maps APIでマッシュアップ


今回は、Google Maps APIとHeartRails Expressの最寄駅情報取得 APIを連携させて クリックした場所の最寄り駅を取得してみます。


いわゆるマッシュアップというやつですね。

まずはGoogle Maps APIですが、これは思ったより簡単に使えます。
version3になってから、APIキーも無しで使うことが出来るようになり、何の準備もなくScriptを書き始められます。


ScriptタグでGoogle Map APIのJavaScriptを読み込みます。

<script type="text/javascript"
 src="http://maps.google.com/maps/api/js?v=3&sensor=false">
</script>

Body要素の中にMapを表示するためのdiv要素を配置しておきます。
<div id="map_canvas"></div>


Mapを表示するための関数を書きます。
この関数をbody要素のonloadなどに仕込んで利用します。
function initialize() {
 //表示位置
 var myLatitude = 35.147055906927214;//経度
 var myLongitude = 139.150131046772;//緯度
 //Mapの表示位置、表示方法などの設定値
 var mapOptions = {
  center: new google.maps.LatLng(myLatitude, myLongitude),
  zoom: 15,//初期のズームレベル
  mapTypeId: google.maps.MapTypeId.ROADMAP
 };
 //Mapを表示するdiv要素と設定値を渡す
 var map = new google.maps.Map(
  document.getElementById("map_canvas"),mapOptions);

 //Mapがクリックされた時のリスナーを登録
 google.maps.event.addListener(map, 'click', clickMap);
}



次に、HeartRails Expressの最寄駅情報取得 APIを利用します。

とてもシンプルなAPIで、URLに以下のように経度緯度のパラメータをつけてリクエストを投げると、最寄駅の情報を返してくれます。
レスポンスはXMLとJSONの二択でそれぞれURLが異なり、今回はJSONを使います。
http://express.heartrails.com/api/json?method=getStations&x=135.0&y=35.0


返ってくるJSONの構造は、responseフィールドの中に、stationフィールドがあり、その中に3つぐらいの駅情報が配列として入っています。
都市部などで多いと10ぐらい入っていたりもしますが、基準はよく分かりません。
駅までの距離が近い順に格納されていて、見つからない場合は空っぽのようです。

これをAjaxで拾ってくれば終わりかと思ったのですが、まったくうまくいきません。

NETWORK_ERR: XMLHttpRequest Exception 101

とか文句を言ってまったく相手にしてくれない。
結構な時間悩みに悩んだんですが、普通にクロスドメインはダメなんですね。

で、JSONPに行き着いた訳ですが、これ完全にscriptタグの悪用なのではないでしょうか。

クロスドメインでデータの読み込みが出来ないブラウザの仕様を回避するために、動的にappendChildしたscriptタグから外部scriptファイルを読み込むふりをして、外部データを拾ってきてしまうという。。
なんだか詐欺みたいな仕様です。

その詐欺師コードが以下。
function clickMap(event) {
 heartrailsURL = "http://express.heartrails.com/api/json?method=getStations&";
 heartrailsURL += "x=" + event.latLng.lng() + "&";
 heartrailsURL += "y=" + event.latLng.lat() + "&";
 heartrailsURL += "jsonp=getStation";//JSONPのコールバック関数
 var script = document.createElement('script');
 script.src = heartrailsURL;
 document.body.appendChild(script);
}

//コールバック関数
function getStation(result) {
 var resultStr = "";
 for(i = 0; i < result["response"]["station"].length; i++) {
  resultStr += result["response"]["station"][i].line + " ";
  resultStr += result["response"]["station"][i].name;
  resultStr += "駅までの距離:" + result["response"]["station"][i].distance + "\n";
 }
 alert(resultStr);
}

普通に動きました。

Google Maps APIがテーマだったのですが、何よりJSONPに感動しました。

Read More...