ek さん
高木さん
細川さん
c-yan です.
いくつかフォローアップに気付いたので.
> >サービスは数ヶ月とか、年オーダーで走り続けるのですが・・・.
> だから、しっかりデバッグしないと・・・ ...^ ^);。
バグがなくてもメモリ不足になることがあります.
メモリのフラグメンテーションです.
オブジェクトのサイズは一定ではないので、端数が空いているけど使えない状態になることがあります.
# HDD のフラグメンテーションは、性能が落ちるだけで済みますが、メモリは連続領域であることが要求されるので
これによりメモリ使用のシナリオによっては、開放漏れがなくてもメモリ不足になることがあります.
GC の場合はコンパクション機能があれば勝手に解決されます.
現実世界の例としては
Apache: 対策として一定回数リクエストを受けたらプロセスを潰して新しいのを立てる
などがあります.
そういった、メモリ使用のシナリオによってはプログラムの本質とは関係ないことをしないといけなくなることがあります.
他の例としては Firefox が長時間使い続けるとメモリの使用量が増えていくなどもそうです.
Chrome はタブをプロセスに紐付けて、タブを閉じるたびにOSに回収させて防いでいますが、CPU使用量とメモリ使用量がトレードオフで大きくなっています.
Firefox は同時に100タブ開くのも余裕ですが、Chrome では厳しいです.
# 余談ですが、Firefox は長時間立ち上げておくとメモリ不足でクラッシュする運命にあるせいか、クラッシュしても問題なく継続できるようになってて、
# あまりクラッシュが気にならないというレベルになってしまいました(^^;
# あ、MS-Office も割とそうだな
高性能なメモリアロケータはフラグメンテーションが起きにくくなっていますが
完全では当然なく (Firefox は jemalloc 使ってるけどあの通りです)
フラグメンテーションが起きにくい代わりに、最初から端数を捨ててかかっているなどのオーバーヘッドもあります.
また、アロケーション、デアロケーションが重くなっており(開放によって連結できるところが出来たら連結するなどの処理とか)
トータルのアロケーション・デアロケーションコストがGCを使ったほうが少ないシナリオもあります. (GC 環境下でのアロケーションは軽い)
これはコンカレントGC環境下では更に発生しやすいです.
コンカレントGC: アプリケーションを走らせつつ、並行でGCをする. 当然停止時間は短い. 総CPUコストは上がるが、CPUがネックでなければ実実行時間は劇的に改善される. 最近の多コア環境ではかなり有効
別の話題としてメモリがフラグメンテーションしないので、CPU のキャッシュの利用効率が上がって、速度が上がることもあるそうです.
更に別の話題として、OS から取得したメモリブロック(チャンク)にオブジェクトが一個だけ残って返却できないケースでは、GC の場合コンパクションで移動して返却できるようになるので、
メモリ使用量が減ることもあるそうです. (Firefox はそれによるメモリ使用量も多い)
> あらゆるWebシステムは「リアルタイム性が高い」ので、「Webシステムを書く際に Java を選ぶのがおかしい」言われているような気が・・・。
世界で一番アクセスが多い Twitter が Ruby/Java で、Facebook が PHP なわけで、Web システムがリアル性が高いというのが、そもそもいろんな意味でおかしいような.
そもそも、Web アプリケーションで、非GC言語って0.1%もいなくありません?
前提がおかしいせいで結論がおかしいですよね、明らかに.
あと、Web アプリは Web 層はスケールアウトで性能が稼げるので、だいたいボトルネックはデータ層です.
DB はC言語でかかれててGC使ってないしー.
その DB のボトルネックはたいてい IO で、CPU でもメモリでもないしー.
SSD が Web アプリの性能をアクセラレーションしまくってることこの上ない昨今です.
> 非常に大きいメモリブロックを最初に確保し、その中で独自のアルゴリズムでメモリの割り当てを行います。
GC は新規割り当て時にメモリ不足じゃないと普通は走らない (Firefox みたいに例外もあります)ので、それをやれば GC 環境下でも同じです.
たいていのGC付き言語は生でメモリを触るのがめんどくさいんで、優位性はケースバイケースですが.
また、C# の場合は large object は特別扱いされて効率的ですし、ピンで止めてしまえばGC対象外になります.
あと C# は普通に HeapAlloc 呼べるので GC 対象外のメモリ確保は容易ですし、ポインタ使えます. (C# 的には行儀悪い扱いになりますが)
D言語みたいなハイブリッド言語だと、最初からGC対象外のメモリ確保が出来たりGC止めたりできます.(都合よくミックスできる)
> 最近はGCの高速化もかなり実現しているようですが、リアルタイム性の高いシステムをJavaで書く時はGCのオーバーヘッドにたいへん気を使う必要があり、精神衛生によくないのではないでしょうか。
ゲームに組み込まれるGC付き言語は参照カウントかインクリメンタルGCがついていることが多いです.
ポーズ短いです.
インクリメンタルGC: 必要なメモリを確保したら適当なところで打ち切る. 停止時間は当然短くなる.
> ということで、私は世間がGC、GCと騒ぐのが昔から理解できないのですが、皆さんはどうお考えですか。
と、GC もいろいろ進化してて、いろんなケースが OK になったり、優位になっていたりするのですが、
そういうことを知らないまま使わないことを肯定するために騒ぐ人が少なくなく・・・.
まずきっちり使ってから語りましょう.
アセンブリ言語の方が性能限界が出せるけど、C言語の方が生産性がよいため、
同じ時間をかけるのであれば、C言語の方が性能が出るという現実と同じように、
非GC言語の方が性能限界が出せるけど、GC付き言語の方が生産性がよいため、
同じ時間をかけるのであれば、GC付き言語の方が性能が出るという現実だと思っています. (一部領域のアプリケーションを除く)
また、CPU もメモリも過剰気味で、IO が性能を決めることが多くなっており、
GC がそもそも気になること自体ほとんどなくね?って感じです.
みなさん毎日 JavaScript の GC にイライラしてます?
> Android は(いわゆるPCと比べ)貧弱なハードです。
Android は珍しく実際に残念な例で、貧弱なハードに Google が新たに実装したせいで枯れてないへっぽこな VM という
二重苦だったのですが・・・最近は PC の1/4くらいの性能のCPUに、あんまり変わらない量のメモリになってしまい
正直なところ物量で解決されてしまうのは時間の問題な気がします.
実際に Windows 95 出たてのころの Java とか実用性の欠片もなかったなあと.
歴史は繰り返す.
余談:
GC のポーズ時間を決めるのは、メモリ使用量なわけですが
(メモリ使用量が倍だと倍というわけではなく、参照グラフがあるので O(nlogn) だと思われる)
逆に言えば、複数のプロセスに分けてしまえば短くなります.
本質ではないことをするのはと言っておいてするのかよという向きがあるかもしれませんが、
Web アプリケーション方面に置かれましては、最近は設定だけで勝手にそうなるようどこかの誰かが実装してくれていたりすることが多いです.
以上です.
メンバーで使える掲示板を活用しよう!
http://ad.freeml.com/cgi-bin/sa.cgi?id=j1D3I
------------------------------------------------------[freeml byGMO]--