- - PR -
スレッドとメモリについて
| 投稿者 | 投稿内容 | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2004-03-11 16:00
いつもお世話になっております。
早速ですが、下記のスレッドを実行すると使用メモリが異常に上がります。
例えば"run()"メソッドのWhile文の中で"test()"メソッドを実行しない場合は メモリが異常に増える事はありませんでした。 そこで原因は"test()"メソッドのArrayListにあると考えました。 しかし原因がわかりません。 "test()"メソッド内部でNewしているのだから、"test()"メソッドが終了した時点で NewしたArryaListは解放されるのですよね? 環境は OS= Windows2000 開発ツール = JBuilder8 JDK = 1.2 [ メッセージ編集済み 編集者: taka 編集日時 2004-03-11 16:02 ] | ||||||||||||
|
投稿日時: 2004-03-11 16:25
どもも。がるともうします。
Javaはそこまで詳しくないのですが。
とは限らないですね。 この辺の、いわゆる「delete演算子のないタイプの言語」の開放のタイミングは 2フェーズから成っていて ・開放が「可能になる」 ・実際に開放する です。 で、メソッド終了時はあくまで「開放が可能になる」だけであり、 即時開放になるかどうかは別になります。 っていうか、通常適当なタイムラグは空くことのほうが多いです。 っと、ここまでがわりとベーシックな見方かと思います。 以下、推測というか妄想というか。 コードを見ていると、test()という関数をループしてCallしてますが。 もしJavaが ・test関数が終了するときに、内部で取得したメモリの参照評価を行う のであれば問題がないのですが、 ・適当な時間軸で「test関数が生きているかどうか」を基準に参照評価を 行う ようなパターンの場合、ほとんどのタイミングで ・test関数自体は生きている ために、メモリの開放は「まだ」という判断を下す可能性があります。 この辺はどんなもんなんでしょうかねぇ? > Javaに詳しい諸氏 ガベージコレクションで泣いているケースは結構あちこちで見ているので。 場合によっては、何らかの「メモリを節約するコード」を書いておいたほうが よい…のかもしれません :-P | ||||||||||||
|
投稿日時: 2004-03-11 16:28
解放の対象になるだけです、解放のタイミングはVMが決めます。 [追記] かぶった・・・がるがるさんの投稿をお読み下さい [ メッセージ編集済み 編集者: ぽん 編集日時 2004-03-11 16:31 ] | ||||||||||||
|
投稿日時: 2004-03-11 16:58
unibon です。こんにちわ。
試しに、つぎのようにかなり変形して動かしましたが、使用メモリはさほど増加しませんでした。
ちなみに実行はバージョン 1.4.2 で、Windows XP 上で、 java -verbose:gc Hoge のような感じです。出力はほぼ、 [GC 601K->89K(1984K), 0.0003092 secs] となって安定します。
バージョンが 1.2 であることに依存している? あるいは明示的に new Thread() のようなことをしないと再現しない? | ||||||||||||
|
投稿日時: 2004-03-11 17:12
待ったなしでブンブンループを回してるから、ガベージコレクションのスレッドがあまり動けていないんじゃないですか?
| ||||||||||||
|
投稿日時: 2004-03-11 17:15
がるがるさん、ぽんさん、unibonさん、貴重なご意見ありがとうございました。
がるがるさん >何らかの「メモリを節約するコード」を書いておいたほうが >よい…のかもしれません とは?どのようなコードを書くとメモリの節約ができるのですか? unibonさん >バージョンが 1.2 であることに依存している? うーん・・・ あまり聞いた事がないのですが、そういった可能性もあるのですね・・・ ところで、"test()"メソッドを下記のように書き直した結果メモリの異常な上がりはありませんでした。 aryListはメソッドの外でprivate定義しました。 "For"文が原因?!
[ メッセージ編集済み 編集者: taka 編集日時 2004-03-11 17:29 ] | ||||||||||||
|
投稿日時: 2004-03-11 17:31
処理内容ではなく、単純にスレッドを使ってるからヒープを食べてるだけではないでしょうか?
| ||||||||||||
|
投稿日時: 2004-03-11 18:06
ども、がるです。
まぁ手法は色々あるのですが。takaさんが書かれている「Private定義」もまた、 メモリ節約の方法の一つですね。 …と、ここで終わると読んでいる他の人で「え???」って人もあるいは いるかもしれないので、もうちょっと細かく砕いてみます。
において、必要な領域は「つねに新しいものを確保する」ロジックになっています。 そうですね。例えば「newしてデータをaddしていくのに必要なaryList」のメモリの 量を1kバイトだと仮定してみましょう。 既存のロジックの場合、例えばtestが10回回ると、1k * 10回で、10kのメモリが 必要になります。また、メモリの確保自体がそんなに軽い作業ではないのと、new という「インスタンスを生成する」作業は意外と重かったりするときがあります。 一方で
の場合、少なくとも「メモリは一回確保したものを使いまわす」うえで「newが 一回しか走らない」ために、特にtest()をぶん回す回数が多ければ多いほど、 作業に必要なコストに開きが出てきます。 大雑把な数式で書くと、双方には a(n-1) + c*b(n-1) ただし a = (new ArrayList())にかかる時間またはコスト b = データ一つをaddするさいに必要なメモリを確保するための時間またはコスト c = 一回のtest()でデータをaddする回数 n = test()をループでぶん回す回数 分の時間、またはコストの差が生じます。nが大きければ大きいほど、差が 顕著になるのがなんとなく予想できるかなぁ、と思います。 # 最適化がない、と仮定した場合の計算式ですが :-P このあたりは「とある命令が、実際にはコンピュータの中でどのようなCPU命令に なってどのようなメモリ確保が行われるのか?」をきちんと意識しておいたほうが よい好例です。 まぁ結構大変だと思うのですが ^^; ある程度以上大きなもの、重いものを扱うときには重要な考え方だと思います。 [ メッセージ編集済み 編集者: がるがる 編集日時 2004-03-11 18:07 ] | ||||||||||||
