疑問点の要約
例えば、"山田太郎"という文字列を表すString型のインスタンスのメモリ使用量は同一バージョンのJVM上では同じになると思っていたが、ライブラリを用いて測定したところ、プログラムを実行する環境により異なっていた、なぜ違いが生じたのか?
質問に至る背景、経緯
・Javaプログラムでメモリ使用量の削減を行いたい。
・実際のメモリ使用量を測る(現状のメモリ使用量、コード修正による効果の測定)ため、java-sizeof等のインスタンスのメモリ使用量を調べるライブラリを使用した。
・測定を行う中で、同一内容のデータオブジェクトであってもjava-sizeof等のライブラリが出力する使用メモリの値はプログラムを実行する環境により異なる、ということに気づいた。
・当初の目的はメモリ使用量の削減だが、そのためには「自分が見ているものが何なのか?」という理解も必要と考え、この結果となる理由を知りたいと思ったが、いまいちどういった方面から調べると答えにたどり着けるのかがわからなかった。
実験に使用したコード
Java
1 String str1 = "abcdefghij"; 2 3 System.out.println("str1 = \"abcdefghij\" size(byte) -> " 4 + RamUsageEstimator.sizeOf(str1)); 5 6 7 String str2 = "山田太郎"; 8 9 System.out.println("str2 = \"山田太郎\" size(byte) -> " 10 + RamUsageEstimator.sizeOf(str2));
結果
<環境A> str1 = "abcdefghij" size(byte) -> 64 str2 = "山田太郎" size(byte) -> 48 <環境B> str1 = "abcdefghij" size(byte) -> 80 str2 = "山田太郎" size(byte) -> 64
環境の違い
環境A:
WindowsOS(64bit)上のEclipseから実行>Javaアプリケーションを使用して実行。
環境B:
WindowsOS(64bit)上でビルド済みjarをコマンドライン上からjavaコマンドを使用して起動。
環境A、Bどちらもマイナーバージョンまで同じOracleのJava8のJDKを使用。
(環境について、どのような情報を記載すると回答が得られそうか、
ハードウェアなのか、ソフトウェアなのか、
それともそのような情報はあまり要らないのか…、
ということが今一つわからないため、この程度しか書けないのですが、
回答にはこのような情報が必要、ということがあれば教えてください。)
Javaコマンドのオプションによる結果の違い(追記)
環境により結果が変わると思っていたのですが、
同じ環境でもjavaコマンドのオプションで-Xms32g -Xmx64gをつけるかどうかで、
結果が変わるということがわかりました。
具体的には環境Bでつけていた場合は
>java -jar -Xms32g -Xmx64g *****.jar str1 = "abcdefghij" size(byte) -> 80 str2 = "山田太郎" size(byte) -> 64
となるのですが、
環境Bでもつけていない場合、
>java -jar *****.jar
や
>java -jar -Xms4g -Xmx8g *****.jar
では、
str1 = "abcdefghij" size(byte) -> 64 str2 = "山田太郎" size(byte) -> 48
となり、環境Aと同じになりました。
なので、もしかしたら環境の違いではなく、こちらが本質なのかもしれません。
逆に環境Aで-Xms32g -Xmx64gを指定したらどうなるのかは、
そんなにメモリを搭載していないため、確認できていません。
メモリ使用量測定に使用したライブラリ(pom.xmlの記載)
<dependency> <groupId>com.carrotsearch</groupId> <artifactId>java-sizeof</artifactId> <version>0.0.5</version> </dependency> <dependency> <groupId>org.openjdk.jol</groupId> <artifactId>jol-core</artifactId> <version>0.14</version> <scope>provided</scope> </dependency>
(上記のコード例ではjava-sizeofの方を記載しましたが、jol-coreを使用した場合も結果は同じ値になりました。)
System.out.println(System.getProperty("os.arch"))の出力結果
(情報追加依頼により追記)
System.out.println(System.getProperty("os.arch"));
の出力結果は環境A、Bともに同じで、"amd64"でした。
知りたいこと
1.環境により同じデータのインスタンスであっても異なるメモリ使用量となるのは「普通のこと」なのか?それとも、「本来は同じになるはず」…だが、自分の何らかのミス、勘違いにより異なっているのか?
2.上記1が「普通のこと」であった場合、「なぜ出力される値は異なるのか?」。そうでなく、「本来は同じになるはず」の場合、異なっているのにはどのような原因が考えられるのか。
3.java-sizeof等のライブラリは何の値を出力しているのか?「実際のメモリ使用量」を出力するものなのか?
4.何らかの要素(パラメータ?)により、同一内容のインスタンスでも使用メモリ量が変動するのだとしたら、明示的にそれらを指定することによりメモリ使用量をコントロールできないか?
5.仮に環境ごとに使用メモリ量が異なるのは仕方のないことだったとして、環境Aでインスタンスの使用メモリ量(としてjava-sizeof等のライブラリが出力する値)が減少するようなプログラム上の修正を行えば、それは環境Bでもメモリ量削減に有効なのか。ある環境で「のみ」有効であったり、環境Aでは有効なものが環境Bでは逆効果、というように「逆転」したりすることは無い、と考えてよいものなのか(環境により結果がことなることから生じている不安)。
回答2件
あなたの回答
tips
プレビュー