メモリ増加に関して

513 views
Skip to first unread message

oiem...@ybb.ne.jp

unread,
Feb 10, 2008, 3:03:51 PM2/10/08
to Google-Map...@googlegroups.com
はじめまして。

現在 Google Map API を利用したサイトの制作をしています。
そのサイトはパフォーマンス要件が厳しく、IEのメモリが
不可解な動作をするため、このMLにて質問させて下さい。

◆サイト概要
 約15000件のレコードを Google API を使用し、地図上に
 アイコンを表示する。15000件のほとんどが東京都内と考えられ、
 地図1画面上に表示されるアイコンは最大で2千~3千件程度に
 なると思われる。

◆内部処理概要
 15000件のレコード全てを一息に JavaScript でループさせ表示
 させるとパフォーマンスに支障をきたすと考え、
 現在地図の左上xy座標、右下xy座標を PHP に渡し、表示する必要の
 あるレコードのみを Javascript にわたすよう、設計しています。
 (Google Map の move イベントでその処理がキックされます。)

 PHP と Javascript のデータ連携は, PHP が XML を吐き出し、
 Javascript が DOM で解析するようにしています。
 
◆現状の問題点
 1) Google Map の move イベントをひろうたびに、IE のメモリが
   増加し、減る様子がありません。
   http://zeromemory.sblo.jp/article/437081.html
   一応ここを参考にしたのですが、該当するコードは無いように
   思います。
   どなたかコードの問題点をご指摘頂けませんでしょうか?
  
 2) 200 件のテストデータを表示してみた所、
   CPU 100% になります。DOM が遅いのは分かるのですが、
   他に方法が思いつかないのが現状です。
   (15000件、初期表示時に表示するとおそらく相当遅くなりますよね?)
   従って本題ではありませんが XML 以外で上手く PHP と連携する
   手段が思い当たる方は教えて頂ければ幸いです。
  
◆コード

 全てではありませんが、本題と関係するJavascript のコードです。
 map_view()関数が body onload 時に呼ばれます。
 map_view()関数の中ではshow_current_map()を呼び出し、
 move イベント発生時にもshow_current_map() が呼び出されるよう、
 リスナーに追加しています。
 (具体的な座標は 999.9999 などとし、隠しています。)
 
<script type="text/javascript" charset="UTF-8">
//<![CDATA[

var map;
var icon1;
var icon2;

var marker = Object();
var conten = Object();

/**
* body onload 時にコールされる。
*/
function map_view()
{
map = new GMap(document.getElementById("map"));
map.addControl(new GLargeMapControl());
map.centerAndZoom(new GPoint(999.99999999, 99.9999999), 4);

icon1 = new GIcon();
icon1.image = "marker.png";

show_current_map();
GEvent.addListener(map, 'move', show_current_map );

}
/**
* XML より指定タグ名のデータ配列を取得
*/
function get_tag(httpObj,tagname){
return httpObj.responseXML.getElementsByTagName(tagname);
}
/**
* get_tag で取得したデータの(単一の)ノードを取得
*/
function get_node(tag){
return tag.firstChild.nodeValue;
}

/**
* マーカーを配置する。show_current_map()からコールされる。
*/
function put_icons(httpObj){
marker = null;
conten = null;
marker = Object();
conten = Object();

var elm_x = get_tag(httpObj, 'x');
var elm_y = get_tag(httpObj, 'y');
var elm_id = get_tag(httpObj, 'id');

var elm_address = get_tag(httpObj, 'address');
var elm_lank = get_tag(httpObj, 'lank');
var elm_category_major = get_tag(httpObj, 'category_major');
var elm_category_minor = get_tag(httpObj, 'category_minor');
var elm_tel = get_tag(httpObj, 'tel');
var elm_fax = get_tag(httpObj, 'fax');
var elm_url = get_tag(httpObj, 'url');

for(var i = 0; i<elm_id.length; i++){
var id = get_node(elm_id[i]);

var detail =
get_node(elm_category_major[i]) + '<br />' +
get_node(elm_category_minor[i]) + '<br />' +
get_node(elm_lank[i]) + '<br />' +
get_node(elm_address[i]) + '<br />' +
get_node(elm_tel[i]) + '<br />' +
get_node(elm_fax[i]) + '<br />' +
'<a target="_blank" href="' + get_node(elm_url[i]) + '">' + get_node(elm_url[i]) + '</a>';

marker[id] = new GMarker(new GPoint(get_node(elm_x[i]),get_node(elm_y[i])), icon1);
conten[id] = detail;

map.addOverlay(marker[id]);
eval ('GEvent.addListener(marker["' + id + '"], "click", function(){ marker_click("' + id + '"); });');
}
var elm_count = httpObj.responseXML.getElementsByTagName('count');
document.getElementById("count").innerHTML = elm_count[0].firstChild.nodeValue;
}
/**
* 現在地図のマーカーを配置。
*/
function show_current_map(){
var xy = map.getBoundsLatLng();
var url = "http://localhost/xxx/html/contents/get_current_map.php?" +
'minX=' + xy.minX + '&' +
'minY=' + xy.minY + '&' +
'maxX=' + xy.maxX + '&' +
'maxY=' + xy.maxY ;
new Ajax.Request(url, { method: "get", onComplete: put_icons } );
var xy2 = map.getCenter();
document.getElementById("show_x").innerHTML = xy2.lng();
document.getElementById("show_y").innerHTML = xy2.lat();
}

/**
* マーカークリック時のポップアップ表示
*/
function marker_click(n)
{
marker[n].openInfoWindowHtml(conten[n]);
return false;
}

//]]>
</script>

◆補足
 PHPは以下のようなXMLを返却します。
 
 <map>
<count>3</count>
<point>
<id>11111</id>
<x>999.9999999</x>
<y>99.9999999</y>
<address>東京都豊島区</address>
<lank>1</lank>
<category_major>大分類</category_major>
<category_minor>小分類</category_minor>
<tel>03-1111-1111</tel>
<fax>03-2222-2222</fax>
<url>http://xxx.xxxx.xxxx.xxxx.xxx</url>
</point>
</map>


長文となりましたが、どなたかアドバイス頂けますでしょうか。
宜しくお願い致します。

superbom

unread,
Feb 10, 2008, 5:32:10 PM2/10/08
to Google-Maps-API-Japan
こちらはご覧になられましたでしょうか。

ブラウザのメモリリークを防止
http://code.google.com/intl/ja/apis/maps/documentation/#Memory_Leaks

oiem...@ybb.ne.jp

unread,
Feb 11, 2008, 2:34:32 AM2/11/08
to Google-Maps-API-Japan
早速の返信、ありがとうございます。

On 2月11日, 午前7:32, superbom <yamaokakazut...@gmail.com> wrote:
> こちらはご覧になられましたでしょうか。
>
> ブラウザのメモリリークを防止http://code.google.com/intl/ja/apis/maps/documentation/#Memory_Leaks

GUnload()は move イベント時にコールしてから本処理を行うよう、
既に試していましたが、アイコンが全く描画されなくなってしまうため、
消していました。

body onunload にもGUnload()を一応書いていますが、今回は ajax でアイコン配置するため、
onunload イベントまで到達しないように思います。

初回の質問メールから、以下の修正を行いました。が、やはりメモリが増加します。

◆変更1:map.clearOverlays();をアイコン再配置前にコール
◆変更2:GEvent.removeListener(click_event); をアイコン再配置前にコール
◆変更3:DOMを使用しない。タブ区切りテキストを用いてPHPと連携する。

本件とは別の話で、15000件程度のデータを画面上に配置するテストを行ったのですが、
ほぼフリーズ状態となってしまい、また、1000件程度のデータを画面上に配置し
地図をドラッグするテストでも、ドラッグを続けるたびにメモリが増加し、ほぼ使いものに
なりませんでした。

従ってクライアントサイドでのアイコン描画は現実的ではないと考え、
Google Map 使用は断念しようと思います。

とはいえ、これでクローズするのも勿体ないので、メモリ増加に関する件で
同じ経験をお持ちの方がいらっしゃいましたら、アドバイス頂ければ幸いです。

ありがとうございました。

>
>
> > はじめまして。
>
> > 現在 Google Map API を利用したサイトの制作をしています。
> > そのサイトはパフォーマンス要件が厳しく、IEのメモリが
> > 不可解な動作をするため、このMLにて質問させて下さい。- 引用テキストを表示しない -
>
> - 引用テキストを表示 -

Masashi.K

unread,
Feb 27, 2008, 11:30:34 PM2/27/08
to Google-Maps-API-Japan
200件とか、そうゆう膨大な数のアイコンを表示しようとしなければ良いんじゃないでしょうか。

例えば、ズームレベルが16以上ならその範囲内で表示する数のアイコンは限られるでしょうし、
ズームレベルが10程度の(例えば東京全体を見るような場合)では、アイコンを代表的なものや
ズームアップするアイコンなど、数を減らす工夫をするべきです。

仮に15000のアイコンを日本全国に均等に配置できたとしても、数が多すぎで
ユーザは使いにくいことは明瞭でしょう。

その辺りを考慮すれば解決できることだと思います。
(Google地図でさえ、検索は10件ごとの表示なんだし・・・)

naom

unread,
Feb 28, 2008, 3:22:14 AM2/28/08
to Google-Maps-API-Japan
> 従って本題ではありませんが XML 以外で上手く PHP と連携する
> 手段が思い当たる方は教えて頂ければ幸いです。
JSONをGDownloadUrl()で受け取ってeval()!
なんてダメですかね。

JSONだったらXMLよりもかなりデータサイズが少なくなります。
なのでメモリリークの度合いも少しは低くなるかもしれません…。

あと下記ページには「eval関数は非常に高速です。」と書いてあります。
DOM(が何なのかはよく知らないですが)よりは早いのかも?
ただ、セキュリティ面での心配もあるようですのでご注意を。
http://d.hatena.ne.jp/brazil/20050915/1126717649

補足ですが、上記ページで紹介されてるjson.js(もう存在しない?)を
Google Maps APIと一緒に使うと何らかの不具合が出てたような。。

naom

unread,
Feb 28, 2008, 4:10:28 AM2/28/08
to Google-Maps-API-Japan
またもや不確かな情報を垂れ流しますが、
http://koti.mbnet.fi/ojalesa/exam/events_v22.html
でグリグリとしてみた感じ、moveイベントを捕捉するのは無謀な気がします。
moveendなどに変更できそうなら、そうしてみた方が軽くなるのではないでしょうか。

あと、たくさんのマーカーを一気に表示するようなときには、
http://www.kawa.net/works/js/8queens/nqueens.html
などを参考に並列処理とやらを組めば体感的にかなり軽くなります。
描画時に一時的にフリーズしちゃうような場合だと特に有効だと思います。
Reply all
Reply to author
Forward
0 new messages