- - PR -
セッションオブジェクトについて
| 投稿者 | 投稿内容 | ||||
|---|---|---|---|---|---|
|
投稿日時: 2003-08-19 13:35
お世話になってます。
現在、Servletで動的に加工したイメージをアプレットに表示するプログラムを作って います。イメージそのものはかなり大きく、Servlet内で読み込んだイメージはアプレット からの再読み込み指示があるまでメモリ(イメージオブジェクト)に保持しています。 アプレットから部分表示や縮小表示の指示があると、システムの都合上、JPEGやGIFなどの 形式でアプレットに送らず、バイト配列のストリームとしてアプレットに送ります。 そのため、イメージオブジェクトからint型の配列に PixelGrabber を使って落とし込ん でます。 で、その落とし込みようの巨大(800*800)なint型配列は、現在では複数スレッドが共有 して使うインスタンス変数として宣言しており、そのままだとイメージが崩れるおそれが あると思うので、イメージを配列に落とし込むところからアプレットに出力し終えるところ までを、synchronized で排他処理をかけています。 しかし、この方法では同時実効性にかけると思います。また、セッションのたびにint型 配列を作ることも考えたのですが、巨大オブジェクトをボコボコと作るのは、パフォー マンスとメモリ領域を圧迫すると思いました。 具体的に実験したわけではないので、どれほどかはわかりませんが・・・。 そこで、セッションオブジェクトというものに注目しました。 セッション内でオブジェクトを保持するようですが、今回のような使い方でも有効で しょうか?今回の場合は、オブジェクトの値を保持したいわけではなく、大きなメモリ 領域を保持したいので、なんか使い方が違うような気もしますが・・・。 セッションオブジェクトの具体的な内部的な動作はよくわかりませんが、オブジェクトの 内容をファイルか何かに落としておいて、オブジェクト取得時にインスタンスの生成と 保持した内容の読み込みをやってるなら、今回の使用方法では逆効果です。 今回のような場合はどういった方法が効果的でしょうか? [ メッセージ編集済み 編集者: maru 編集日時 2003-08-19 13:37 ] | ||||
|
投稿日時: 2003-08-19 16:30
こんにちわ。
そのような巨大なオブジェクト保持を目的として Sessionを使用すると、個人的には痛い目に会い そうな予感がします。 要求毎にオブジェクトを生成するのか? Session毎にオブジェクトを生成するのか? 要はメモリか?処理性能か?ってことでしょうか。 しかし、いちいちオブジェクト作ってた方が 良い気がしてならないのですが。。 以前、全検索結果をSessionに保持させて、「次へ」「前へ」 ボタン処理時にはSessionにたまってるオブジェクトから 結果を取得してきて表示ってのをやったことありますが 検索結果数、接続人数によっては恐ろしくメモリ食いました。 結局処理性能は落ちるけど「次へ」「前へ」押下毎に 新規で検索行かせるようにすることで落ち着いたのですが。 私の個人的設計観ですが、Sessionにはなるべく識別系情報 (もっと具体的に言えばString)しか入れないようには考えています。 いくらSessionTimeOutを調節したからと言って同時接続ユーザ数 が多いシステムでは致命的になりかねません。 ではでは。 | ||||
|
投稿日時: 2003-08-19 17:21
unibon です。こんにちわ。
拝見していて私が良く分からなかった点としては、 応答などの速度を早めるために「巨大オブジェクト」の生成のコスト(速度)を節約されたいのでしょうか、 それともメモリ不足に陥るのを避けるためにシステムが使用するメモリ量を節約されたいのでしょうか。 前者ならば、そんなにコストは高くないはずです。 良くは知りませんが、世代別 GC というものもあり、 使い捨てのメモリを確保するのにはそれほど速度的なコストはかからないはずです。 後者ならば、キャッシュの問題になると思います。 キャッシュのために Session を使うのは、 持続時間を細かく制御できないので、逆にコスト高になる恐れがあります。 もしもデータをファイルなどから随時再構築できるのならば、 多少手間はかかるものの SoftReference が便利です。 http://java.sun.com/j2se/1.4/ja/docs/ja/api/java/lang/ref/SoftReference.html あるいは、キャッシュのマネージャを自前で構築するなども考えられます。 | ||||
|
投稿日時: 2003-08-21 09:59
こんにちは。返答が遅くなりました。
ぽちさん、unibonさん返答ありがとうございます。 >応答などの速度を早めるために「巨大オブジェクト」の生成のコスト(速度)を節約され >たいのでしょうか、 >それともメモリ不足に陥るのを避けるためにシステムが使用するメモリ量を節約された >いのでしょうか。 両方です。メモリ生成速度(+GCの実行)とメモリ不足を気にしています。 いい方法を模索中ですが、思いつかない(見当たらない)ので、とりあえず、今回の システムは接続数も接続頻度もそんなに多くなく、メモリも大量につむので、 JavaVM起動パラメータであらかじめヒープを大きく確保するのと、毎回メモリ確保 するようにしようと思います。 | ||||
|
投稿日時: 2003-08-21 14:28
そういうときはプール作るのが良いのではないです? Servletのinit時にいくつか大きなバッファを作っておいて、必要時に取り出して 終わったら返す、と。 DBの接続と同じ理屈ですが。 http://jakarta.apache.org/commons/pool/ こんなものもあることですし。 | ||||
|
投稿日時: 2003-08-21 16:39
グローバルなint[]が一つあるだけなんですよね? イメージを作り直す頻度がそれほど高くないのであれば、 更新する際にint配列を作り直せばよいのではないでしょうか。 /** 共有オブジェクト */ class Shared { int[] pixels; public int[] getPixcels() { return pixcels; } public void setPixels(int[] pixels) { this.pixels = pixels; } } { //イメージ更新処理 int[] newImage = new int[800 * 800]; createNewImage(newImage); Shared shared = getSharedObject(); shared.setPixels(newImage); } { //アプレットに送信 Shared shared = getSharedObject(); int[] image = shared.getPixels(); sendToApplet(image); } これなら同時に利用しているイメージの分しかメモリも消費しませんし。 | ||||
|
投稿日時: 2003-08-21 17:02
あ、もしかしてこのint配列ってのは単なる作業領域としてしか使ってないのでしょうか? (そもそも情報自体を共有する必要は無い?) もしそうなら、まりりさんの挙げられているObjectPoolingが答えですね。 | ||||
|
投稿日時: 2003-08-21 17:49
こんにちは。
そうです。int配列は作業用ですね。 まりりさんの言われるようにオブジェクト・プールを検討してみます。 #そういえば、この間何かの本でこれと同じような話の記事を見たような気が・・・ | ||||
