[mayaa-user:1007] Re: SpecificationCacheのデータサイズを節約したい

Susumu ISHIGAMI [E-MAIL ADDRESS DELETED]
2014年 2月 9日 (日) 18:14:58 JST


石上です。

sugaさん、ご回答ありがとうございます。

> 注意点としては(当然ですが)テストが難しいこと、
> 試行錯誤になるため計測が大変だろうということ、でしょうか。
>
> 実際に、あまり使われないページがどのくらいGCされずに残っているのか、
> どのくらいで使われないと判断すれば良いのか、
> ログを出すなりして数値として計測してから着手しないと、効果が無い方向に
> コストをかけてしまうことになりますので、そこをしっかりやることですね。
>
> 状況が詳細に見えてくれば、違う手段で解決できることもあるかもしれませんし。

そうですね。開発戦略的にはまずはログを出力する部分から試みてみようと思います。
現状、heap dumpを解析すればどの辺りのページがどうなっているか把握できるのですが、
オンラインで見極められる仕組みを作るところからですかね。。。

技術的なところではどうでしょうか?
基本的にはSpecificationCacheの実装を真似して削除する条件だけをカスタマイズする方針で良いかと考えています。
特に注意しないとバグになりやすいポイントなどありませんでしょうか。
曖昧で申し訳ありません。

はじめにsugaさんから頂いた返信で「難しいですね......。」とおっしゃっていたのが、前述の試行錯誤の部分のことなのか、
プログラミング難易度のことなのかが気になりまして。
両方なのかもしれませんね。


2014年2月9日 0:05 suga <ko.suga @ gmail.com>:
> suga です。
>
> # うっかりToになってしまったようですみません。
>
> 2014-02-08 16:40 GMT+09:00 Susumu ISHIGAMI <susumu.ishigami @ gmail.com>:
>> そこで、唐突な質問で大変恐縮ですが、もし行う場合の注意点や難易度を教えていただくことはできませんでしょうか。
>
> 注意点としては(当然ですが)テストが難しいこと、
> 試行錯誤になるため計測が大変だろうということ、でしょうか。
>
> 実際に、あまり使われないページがどのくらいGCされずに残っているのか、
> どのくらいで使われないと判断すれば良いのか、
> ログを出すなりして数値として計測してから着手しないと、効果が無い方向に
> コストをかけてしまうことになりますので、そこをしっかりやることですね。
>
> 状況が詳細に見えてくれば、違う手段で解決できることもあるかもしれませんし。
>
> --
> suga ( ko.suga @ gmail.com )
>
>
> 2014-02-08 16:40 GMT+09:00 Susumu ISHIGAMI <susumu.ishigami @ gmail.com>:
>> 石上です。
>>
>> 以前、私の下記質問に対し
>>
>>>>また、サイズが大きくなってしまうのならば、せめてリソースを管理したい心情がありますので、
>>>>例えばフォルダごとに50MBまでというように、グルーピングして最大容量を固定したい場合は
>>>>ReferSpecificationをカスタマイズして、requestReleaseを独自実装すれば実現可能なような気がします。
>>>>もしこの認識が合っていましたら、現状ReferSpecificationがprivate classのためにできませんので、
>>>>こちらをカスタマイズ可能にしていただくことはできませんでしょうか。
>>>>(的はずれなことを言っていたら申し訳ありません)
>>
>> sugaさんから以下の回答を頂いております。
>>
>>>SpecificationCache を継承したクラスで #add(Specification) を override したものを作って、
>>>EngineImpl#getCache() を override して SpecificationCache の代わりにそれを
>>>使う、
>>>という方法で実現できないでしょうか。
>>>
>>>細かな調整をしようとした場合、おそらくSpecificationCache もカスタマイズすることに
>>>なるのではないかと思いますので。
>>
>> 本件、真剣に検討しております。
>>
>> 少々大変でも、ヒープのリソースを自分たちの意の通りにコントロールしたい状況にあり、
>> ディレクトリごとのキャッシュの容量を計測したり制限し、最も使われていないキャッシュを排除するような
>> ことを行いたいと思っています。
>>
>> ちょっとこちらの事情を説明してしまいますと、
>> IaaSインフラ上でサービスを運営しておりインスタンスのメモリリソースが運用費用に直結してしまっています。
>> 昨今のサービス運営では、いかにリソースを節約し、コントロールし、エンドユーザーに消費リソースを見える化するかが、
>> 鍵になるのではないかと思われますので、
>> こういったノウハウは他所でも必要になってくるのではないかと思います。
>> もし成果が得られたら可能な限りフィードバックしたく思います。
>>
>> そこで、唐突な質問で大変恐縮ですが、もし行う場合の注意点や難易度を教えていただくことはできませんでしょうか。
>>
>>
>> 2014年1月25日 12:20 Susumu ISHIGAMI <susumu.ishigami @ gmail.com>:
>>> 石上です。
>>>
>>> 素早いご回答ありがとうございます。そうですよね。難しいですよね。。。
>>> SpecificationCacheの内部実装を読ませていただきました。
>>>
>>> ReferSpecificationの
>>> getSpecificationが呼ばれると_survivingCountが0に初期化
>>> requestReleaseが呼ばれるごとに_survivingCountが1加算され、
>>> surviveLimitを超えた時に参照が取り除かれる
>>> という実装になっていますので、使用頻度が高いデータは頻繁にgetSpecificationが呼ばれるので
>>> キャッシュは残りやすくなっているのですね。
>>>
>>> java.lang.refパッケージについて不勉強で申し訳ないですが
>>> requestReleaseが呼ばれるタイミングがよく分からず、
>>> いわゆるFullGCの回数に依存するのか、YoungGCも含めるのかがいまいちわかりませんでした。
>>> ReferenceQueueを使用して、参照が切れたことを検知しているのはわかったのですが。。。
>>>
>>> 現状のアルゴリズムにおいて、
>>>
>>> ・今はあまり使われないキャッシュもOlgGenに格納されていると思われる
>>> ・キャッシュの容量を一定になるように管理したい
>>> ・あまり使われないキャッシュはYoungGCで消されて欲しい
>>> ・頻繁に使われるキャッシュはOldGenに格納されてほしい
>>>
>>> という場合は、surviveLimitが5にて、この状態の場合、surviveLimitを減らすべきという認識でよろしいでしょうか。
>>>
>>> また、サイズが大きくなってしまうのならば、せめてリソースを管理したい心情がありますので、
>>> 例えばフォルダごとに50MBまでというように、グルーピングして最大容量を固定したい場合は
>>> ReferSpecificationをカスタマイズして、requestReleaseを独自実装すれば実現可能なような気がします。
>>> もしこの認識が合っていましたら、現状ReferSpecificationがprivate classのためにできませんので、
>>> こちらをカスタマイズ可能にしていただくことはできませんでしょうか。
>>> (的はずれなことを言っていたら申し訳ありません)
>>>
>>>
>>>
>>> 2014年1月22日 23:50 suga <ko.suga @ gmail.com>:
>>>> suga です。
>>>>
>>>> 難しいですね……。
>>>>
>>>> 不要なprocessorを削るというのはすでにされているようなので、
>>>> あとは共通パターンをcomponentにすることで数を減らす、
>>>> 物によっては独自processor(orカスタムタグ)を作ることでサイズを小さくできるものもあるかもしれません。
>>>>
>>>> ファイルサイズは、現在は単純な serialize なので Zip してしまえば小さくなるでしょうけど、
>>>> その分 serialize / deserialize は遅く重くなるのでトレードオフですね。
>>>>
>>>>
>>>> 早めにメモリから解放されるようにするには、engineのパラメータ surviveLimit を小さくする方法があります。
>>>> これはGC の解放命令を何回無視するかという回数なので heap サイズとは直接関係ありませんが、
>>>> 空き heap を優先させるなら小さくしてみて効果があるか試すのも手でしょう。
>>>> デフォルトは 5 です。
>>>>
>>>> 処理は
>>>> org.seasar.mayaa.impl.engine.SpecificationCache
>>>> にあります。
>>>>
>>>>
>>>> --
>>>> suga ( ko.suga @ gmail.com )
>>>>
>>>>
>>>> 2014/1/22 Susumu ISHIGAMI <susumu.ishigami @ gmail.com>:
>>>>> 石上です。
>>>>>
>>>>> 唐突な相談で申し訳ありません。
>>>>>
>>>>> Mayaaを使用していると、
>>>>> org.seasar.mayaa.impl.engine.SpecificationCache
>>>>> というクラスにテンプレートのキャッシュが蓄積されていきます。
>>>>>
>>>>> ヒープダンプを解析してみると、ここに蓄積されるデータ量は
>>>>> 数百KBのテンプレートファイルでも、1ファイル分で10MB以上になることがあり、
>>>>> 大量のテンプレートを使用しているWebサイトでは、
>>>>> GB単位になってしまいます。。。
>>>>>
>>>>> SoftReferenceを使用しているのでOutOfMemoryErrorになることはなく、
>>>>> さらにアンロードされたとしてもpageSerialize機能が有効であれば、
>>>>> .mayaaSpecCacheディレクトリにシリアライズされたデータが保存されているので、
>>>>> 再ロードするときのコストが最小限に押さえられます。
>>>>>
>>>>> 大変良く作られていますねw
>>>>>
>>>>> では、あるのですが、やはりファイルからロードするとメモリにキャッシュされているよりは大分遅いですし、
>>>>> ヒープのOldGenの大半を専有してしまうので、なるべく減らしたいのが心情です。。。
>>>>> ヒープサイズが慢性的に多すぎるため、GCの発生頻度なども上がってしまい、システムの安定性を低下させてしまいますので、
>>>>> 消費量が少ないなら少ないように抑えたく思います。
>>>>>
>>>>> そこで、なんとかキャッシュの容量を節約する方法はありませんでしょうか。
>>>>> それが無理なら、ヒープの割上げ上限(出来れば空きヒープの%指定)が設定できると良いかと思います。
>>>>>
>>>>> 今のところ、キャッシュの容量は単にテンプレートファイルのサイズに依存するのではなく、
>>>>> テンプレートでprocessorと紐付いているほど大きくなることを把握していますので、
>>>>> 「なるべく不要なm:id属性は記述しない」
>>>>> 「長期的に使わない箇所はコメントアウトではなくてテンプレートから消してしまう」
>>>>> とテンプレート作成者に伝えています。
>>>>> _______________________________________________
>>>>> mayaa-user mailing list
>>>>> mayaa-user @ ml.seasar.org
>>>>> https://ml.seasar.org/mailman/listinfo/mayaa-user
>>>> _______________________________________________
>>>> mayaa-user mailing list
>>>> mayaa-user @ ml.seasar.org
>>>> https://ml.seasar.org/mailman/listinfo/mayaa-user
>>>
>>>
>>>
>>> --
>>> Susumu ISHIGAMI
>>> susumu.ishigami @ gmail.com
>>
>>
>>
>> --
>> Susumu ISHIGAMI
>> susumu.ishigami @ gmail.com
> _______________________________________________
> mayaa-user mailing list
> mayaa-user @ ml.seasar.org
> https://ml.seasar.org/mailman/listinfo/mayaa-user



-- 
Susumu ISHIGAMI
susumu.ishigami @ gmail.com


mayaa-user メーリングリストの案内