LoginSignup
0
1

More than 3 years have passed since last update.

Javaの要素のメモリ使用量を調べる

Posted at

プリミティブとBox

まずはじめにプリミティブとBox型の配列を作成してどれだけメモリを使用するのか見たいです。

  private static final int NUM = 100_000;

  public static void main(String[] args) {
    long beforeUse, afterUse, div;
    beforeUse = memoryUsed();
    int[] primitive = new int[NUM];
    afterUse = memoryUsed();
    div = afterUse - beforeUse;

    out.println(" -- int[] -- ");
    out.println(div);
    out.println((double)div / primitive.length);

    beforeUse = memoryUsed();
    Integer[] classes = new Integer[NUM];
    afterUse = memoryUsed();
    div = afterUse - beforeUse;

    out.println(" -- Integer[] unset -- ");
    out.println(div);
    out.println((double)div / classes.length);

    for (int i = 0;i < classes.length;i++) {
      classes[i] = i;
    }

    afterUse = memoryUsed();
    div = afterUse - beforeUse;

    out.println(" -- Integer[] set -- ");
    out.println(div);
    out.println((double)div / classes.length);
  }

実行結果

 -- boolean[] -- 
100016
1.00016
 -- Boolean[] unset -- 
400016
4.00016
 -- Boolean[] set -- 
400016
4.00016
 -- byte[] -- 
100016
1.00016
 -- Byte[] unset -- 
400016
4.00016
 -- Byte[] set -- 
448528
4.48528
 -- short[] -- 
200016
2.00016
 -- Short[] unset -- 
400016
4.00016
 -- Short[] set -- 
1923440
19.2344
 -- char[] -- 
200016
2.00016
 -- Character[] unset -- 
400016
4.00016
 -- Character[] set -- 
2402512
24.02512
 -- int[] -- 
400016
4.00016
 -- Integer[] unset -- 
400016
4.00016
 -- Integer[] set -- 
2202512
22.02512
 -- long[] -- 
1048576
10.48576
 -- Long[] unset -- 
400016
4.00016
 -- Long[] set -- 
3105872
31.05872
 -- float[] -- 
400016
4.00016
 -- Float[] unset -- 
400016
4.00016
 -- Float[] set -- 
2706352
27.06352
 -- double[] -- 
1048576
10.48576
 -- Double[] unset -- 
400016
4.00016
 -- Double[] set -- 
3651112
36.51112

1要素あたりのメモリ使用[バイト]

プリミティブ Box型(unset) Box型(set)
boolean / Boolean 1.00 4.00 4.00
byte / Byte 1.00 4.00 4.48
short / Short 2.00 4.00 19.23
char / Character 2.00 4.00 24.03
int / Integer 4.00 4.00 27.06
long / Long 10.49 4.00 36.51
float / Float 4.00 4.00 27.06
double / Double 10.49 4.00 31.06

配列を作成すると決まって16バイト使用しています。
プリミティブでlongとdoubleが想定していたよりもメモリを使用していたのがよくわかりません。
Box型(set)でCharacter以降は20バイト以上使用するので多用は厳禁といったところでしょうか。

Stringクラス

Stringクラスのメモリ使用量を見てみます。

// set empty
for (int i = 0;i < NUM;i++) {
    ary[i] = "";
}
// set new String
for (int i = 0;i < NUM;i++) {
    ary[i] = new String();
}

// set 10digit
for (int i = 0;i < NUM;i++) {
    ary[i] = new String("0123456789");
}
 -- String[] unset -- 
400016
4.00016
 -- String[] set empty -- 
400016
4.00016
 -- String[] set new String -- 
3105872
31.05872
 -- String[] set 10digit -- 
3105872
31.05872

全ての要素にnew Stringすると約31バイト消費します。ですがnew String("0123456789")でも31バイトなのが不思議です。
内部要素のprivate final byte[] value;が常に同じ参照になるからでしょうか。

なので全ての要素が一意になるように直してみました。

for (int i = 0;i < NUM;i++) {
    ary[i] = String.format("%010d", i);
}
System.gc();
 -- String[] set 10digit -- 
4998968
49.98968

1要素あたり49バイトとなりました。

HashMap

HashMapに10万要素入れます。

Map<String, String> map = new HashMap<>();
for (int i = 0;i < NUM;i++) {
    map.put(String.valueOf(i), "A" + i);
}
13632176
136.32176

1要素あたり136バイトと成りました。
実装を見てみないと根拠がわからないので読んでみる必要がありそうです。

ソースコード

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1