- PR -

スレッドとメモリについて

投稿者投稿内容
coasm
大ベテラン
会議室デビュー日: 2001/11/26
投稿数: 237
投稿日時: 2004-03-11 18:56
Javaのバージョンによる相違ですが、1.2.2 と 1.4.2では、
Interger.toSring(int)の実装に相違があって、メモリー消費が大きく違ってくるのです。
(どちらのバージョンでも、String.valueOf(int)は、Interger.toSring(int)を呼び出す点は同じ)

1.2.2が呼び出されるごとに毎回新しいStringオブジェクトを生成するのに対して、
1.4.2では、値が Integer.MIN_VALUEまたは -3〜10 の範囲内だった場合は、
あらかじめ用意してあったStringオブジェクトを返すようになっています。

したがって、(この例の場合は特に)ループ一回当たりに消費するメモリーの量に大きな差ができることになります。
taka
常連さん
会議室デビュー日: 2003/09/22
投稿数: 46
投稿日時: 2004-03-11 19:19
インギさん、がるがるさん、coasmさん、ご意見ありがとうございました。

がるがるさん
>このあたりは「とある命令が、実際にはコンピュータの中でどのようなCPU命令に
>なってどのようなメモリ確保が行われるのか?」をきちんと意識しておいたほうが
>よい好例です。
ハイ、大変に勉強になりました。
話は変わりますが、がるがるさんの「オブジェクト講座」を読ませていただきました。
私のような技術的に未熟な物にも非常にわかりやすく、最後までついていくことができました。
説明下手な私にはがるがるさんの説明の仕方は参考になります。

coasmさん
>Interger.toSring(int)の実装に相違があって、メモリー消費が大きく違ってくるのです
これは知りませんでした。そのような違いをしっかりと頭に入れて進めなくてはいけませんね。
これらのバージョンによる違いは何を見ればわかりますか?
uk
ぬし
会議室デビュー日: 2003/05/20
投稿数: 1155
お住まい・勤務地: 東京都
投稿日時: 2004-03-11 20:50
http://java.sun.com/j2se/1.3/ja/docs/ja/guide/performance/index.html
を読むと、1.2から1.3への間にVMに対して大きな変更が加えられたことがわかると思います。
coasm
大ベテラン
会議室デビュー日: 2001/11/26
投稿数: 237
投稿日時: 2004-03-12 00:57
> これらのバージョンによる違いは何を見ればわかりますか?

JDK/J2SDKにはライブラリのソースコードが入っている
(インストールしたディレクトリの src.jar)ので、
解凍して読んでみましょう。

java.lang とか java.util のコードを読むと、勉強になりますよ。

# 100%が手放しで誉められるコードというわけではありませんが(笑)、

ここで挙げた Integer.toString(int)も、普通に思いつく
「10で割ながら、1桁ずつ下位から処理していく」という実装ではなくて、
「テーブルを参照しながら、2桁ずつ下位から処理していく」という
ちょっと複雑だけど効率の良い実装になっています。

# native method なので処理の内容が見れないとか、
# com.sun.java 以下のパッケージのソースが見れないとか、不満も多々あります。



[ メッセージ編集済み 編集者: coasm 編集日時 2004-03-12 01:03 ]
さくらば
大ベテラン
会議室デビュー日: 2002/11/12
投稿数: 145
投稿日時: 2004-03-12 10:20
こんにちは、さくらばです。

引用:

coasmさんの書き込み (2004-03-12 00:57) より:

JDK/J2SDKにはライブラリのソースコードが入っている
(インストールしたディレクトリの src.jar)ので、
解凍して読んでみましょう。

# native method なので処理の内容が見れないとか、
# com.sun.java 以下のパッケージのソースが見れないとか、不満も多々あります。




native method や hotspot の実装も含めたすべてのソースは公開されていますけど。

http://wwws.sun.com/software/communitysource/j2se/java2/download.html
シュン
ぬし
会議室デビュー日: 2004/01/06
投稿数: 328
お住まい・勤務地: 東京都
投稿日時: 2004-03-12 11:20
短命なオブジェクトの生成個数を抑えるために、インスタンスへの参照のスコープを広げてしまうというのは、トレードオフがあります。メソッドローカル変数からのみ参照できるオブジェクトは、「スレッドセーフ」に設計されていないものであっても、安全に使える可能性が有ります。
GenerationalGCが採用されている新しいJVMでは、短命なオブジェクトの生成および消去のコストは、以前のJVMに比べて格段に低くなっているといわれています。
Collectionは、その実装構造によっては、clear()の作業は非常にコストが高くなる可能性があります。
Collectionについては、毎回新しく生成する方が、安全で、コードも簡潔になる上に、実行時に安上がりである可能性もあるわけです。

ハードウェアやJVMの進化により、短命オブジェクトが原因でメモリ消費量が一時的に増加することは気にしないでプログラミングを行えるようになりつつあります。
スコープの短いインスタンスを豪勢に生成する「富豪的プログラミング」がもたらすコードの簡潔さが、実行時の多少のリソースの浪費による性能劣化に優先する時代が近づいている(アプリケーションの案件によってはすでにそうなっている?)のではないでしょうか。
coasm
大ベテラン
会議室デビュー日: 2001/11/26
投稿数: 237
投稿日時: 2004-03-13 12:04
さくらばさん
> native method や hotspot の実装も含めたすべてのソースは公開されていますけど。

あ、そこは知りませんでした。ありがとうございます。
と思ってさっそくアクセスしたら、つながりませんでした・・・
何故だろう? (wwws.sun.comの名前解決に失敗する)

シュンさん
御指摘の通り、ArrayList#clear や HashMap#clear は、要素数に比例した手間を要する、
比較的高価な処理です。(LinkedList や TreeMap は低負荷ですが)。
「Collectionについては、毎回新しく生成する方が、安全で、コードも簡潔になる」のも
確かだと思います。

というか、Collectionオブジェクトを使い回したとしても、
Collectionに要素を追加する毎にEntryオブジェクトが作られるのは防ぎようがないので、
実際にはオブジェクト生成を抑制する効果はほとんど得られません。

貧乏人的プログラミング?に徹するなら、
この例のようにサイズが予め判明していてしかも要素の挿入や削除を行わないのであれば、
Listではなくて配列を使えばメモリー消費/実行速度の両面で大きく改善できますが・・・
しかし、よほどの理由がない限り、やめておいた方が良いでしょうね
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2004-03-13 19:05
unibon です。こんにちわ。

引用:

unibonさんの書き込み (2004-03-11 16:58) より:
引用:

takaさんの書き込み (2004-03-11 16:00) より:
環境は
OS= Windows2000
開発ツール = JBuilder8
JDK = 1.2


バージョンが 1.2 であることに依存している?
あるいは明示的に new Thread() のようなことをしないと再現しない?


http://java.sun.com/products/archive/index.html
から 1.2.2_17/_017 をダウンロードしてその上で、前回私が書いたコードを動かしてみましたが、別段メモリを極端に消費することはありませんでした。
そもそも、寿命の短いインスタンスがたくさんあったとしても、メモリ消費量が極端に増えると言うことは昔(バージョン1.1のころ)からなかったと思います。もしあったとしたら、数値計算の類のプログラムは常にフルにメモリを使ってしまうことになってしまうのではないでしょうか。

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