@IT会議室は、ITエンジニアに特化した質問・回答コミュニティ「QA@IT」に生まれ変わりました。ぜひご利用ください。
- PR -

sessionに格納されたデータ量の算出方法

1
投稿者投稿内容
RIN
常連さん
会議室デビュー日: 2006/10/11
投稿数: 21
投稿日時: 2009-04-02 18:58
いつもお世話になっております。

sessionに格納されたデータ量の算出するプログラムを作成したいんですが、
何かアドバイスあるいは参照URLを知っている方がいらしゃいましたら、
ご教授お願い致します。
下記、C#版ですが、Javaの場合、同じlibがないみたいです、、、
http://www.atmarkit.co.jp/fdotnet/entwebapp/entwebapp06/entwebapp06_03.html

using System;
using System.IO;
using System.Web;
using System.Runtime.Serialization.Formatters.Binary;

namespace Microsoft.Japan.Mcs.Utilities.Web
{
public class WebUtil
{
public static long CalculateSessionSize()
{
MemoryStream stream = new MemoryStream();
BinaryWriter writer = new BinaryWriter(stream);
HttpContext hc = HttpContext.Current;
foreach (string key in hc.Session.Keys)
{
writer.Write(key);
(new BinaryFormatter()).Serialize(writer.BaseStream, hc.Session[key]);
}
writer.Flush();
long size = stream.Length;
stream.Close();

return size;
}
}
}

かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2009-04-02 19:35
データ量とは、メモリの使用量でしょうか。
直列化後のバイト数でしょうか。

Javaの場合、メモリの正確な使用量を測ることは出来ません。
しかし、JDK5以降であれば、以下のAPIで近似値を取得することができます。
http://java.sun.com/j2se/1.5.0/ja/docs/ja/api/java/lang/instrument/Instrumentation.html#getObjectSize(java.lang.Object)

直列化後のバイト数は、直列化して計るのが早いかと思います。

どのみちオーバーヘッドはそれなりにあります。
目的はストレージやメモリ、サーバのキャパシティの見積もりでしょうか。

RIN
常連さん
会議室デビュー日: 2006/10/11
投稿数: 21
投稿日時: 2009-04-02 23:39
ご返事頂いて有難う御座います。

>データ量とは、メモリの使用量でしょうか。
>直列化後のバイト数でしょうか。

メモリの使用量を計りたいです。

>Instrumentation.html#getObjectSize(java.lang.Object)
有難う御座います。テストしてみます。


>どのみちオーバーヘッドはそれなりにあります。
>目的はストレージやメモリ、サーバのキャパシティの見積もりでしょうか。

目的はキャパシティの見積もりだけではなく、開発ルール(セッションの最小限使用)
も徹底したいのです。

開発のフェーズから最小限なセッションデータ使用を制限したいんですので、
システムのメモリの変化だけではなく、プログラミングの中にセッションに
入れたデータ量も監視したいのです。

開発ルールを厳守しない場合はありますから。。:(








[ メッセージ編集済み 編集者: RIN 編集日時 2009-04-02 23:40 ]

[ メッセージ編集済み 編集者: RIN 編集日時 2009-04-02 23:42 ]

[ メッセージ編集済み 編集者: RIN 編集日時 2009-04-03 00:17 ]
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2009-04-03 00:21
そういうことでしたか。

InstrumentationはTomcatoの起動時に仕掛ける必要がありまして、
仕掛けて起動時にpremainが呼び出されるようにします。
呼び出されたらpremainメソッドの中でInstrumentationのインスタンスを、
どこかのクラスにstaticフィールドに保持するようにします。

後はサーブレットフィルタでリクエスト毎に計測するのがよいかと思います。

参考までに、工夫すればセッションを最低限にすることは可能です。
最近の自分の実装パターンでは、キャッシュ用途等で、
値が消えても困らないような値は格納したりしますが、
業務的な値はユーザを示すキー以外、セッションには格納しません。
自然とステートレスなつくりになりますし、スケールアウトしやすくなります。

そのために、間違ってセッションに格納しないように、
ログインモジュール以外でセッションを取得して値を設定しようとすると、
エラーになるような仕組みにしたりしています。
RIN
常連さん
会議室デビュー日: 2006/10/11
投稿数: 21
投稿日時: 2009-04-03 16:30
かつのりさん、いろいろありがとうございます。

調べましたが、Instrumentation.getObjectSizeはオブジェクトの参照先のオブジェクトサイズまでは量らないようです。
(だから、テストするときに、Stringの長さが変更しても24だけが返ってきました)

インスタンスのサイズを動的に計算しなければならないことが判りました。

ついに、これをやってくれるOpenソースが見つかりました。

:) :)

http://sourceforge.net/projects/sizeof


[ メッセージ編集済み 編集者: RIN 編集日時 2009-04-03 16:32 ]
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2009-04-03 18:20
リフレクションを使って再帰的にフィールドのサイズを取得しているようですね。
こういうのも、実は問題があったりして、
コード:
private static byte[] bytes = new byte[1024 * 1024]  //1M確保

session.setAttribute("b1", bytes);
session.setAttribute("b2", bytes);


というコードの場合、b1の合計とb2の合計では計算上2M弱になりますが、
実際には1M弱で済みます。こういう場合はどうするかというポリシー次第ですが。
RIN
常連さん
会議室デビュー日: 2006/10/11
投稿数: 21
投稿日時: 2009-04-04 15:07
>private static byte[] bytes = new byte[1024 * 1024] //1M確保
>session.setAttribute("b1", bytes);
>session.setAttribute("b2", bytes);

このコードで予想外の動作が出てくるかと思います。
キーb1でバインドされたオブジェクトを更新したら、キーb2でバインド
されたオブジェクトにも更新されてしまいますよね、

メモリ最小限の観点からも
セッションキー<−>オブジェクトをユニークにするべきだよね




1

スキルアップ/キャリアアップ(JOB@IT)