0
votes

i was tracking allocations in my app and i came with very strange behavior when allocating array. This is simple demo of my code -

public class Main extends Activity implements OnClickListener {
    private Object[][] m = new Object[30000][];

    @Override
    public void onCreate(Bundle savedInstance) {
        setContentView(R.layout.main);
        super.onCreate(savedInstance);
        findViewById(R.id.Button01).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        for (int i = 0 ; i < 30000 ; i++) {
            // case 1
            m[i] = new short[20];
            // case 2
            m[i] = new short[2][10];
        }
    }   
}

I run two test cases in which i comment on of the case lines. In case 1 when i am allocating one dimensional array everything seems to be normal

  • before clicking
    • heap size = 5.2 MB
    • allocated = 2.6 MB
  • after clicking
    • heap size = 6.5
    • allocated = 3.9
  • allocated objects
    • 56(allocation) - short[] - allocated in Main.java#OnClick

In case 2 when i am allocating two dimensional array strage things are happening

  • before clicking
    • heap size = 5.2 MB
    • allocated = 2.6 MB
  • after clicking
    • heap size = 8.1 MB
    • allocated = 5.3 MB
  • allocated objects
    • 36(allocations) - short[] - allocated in Array.java#createMultiArray
    • 24(allocations) - short[][] - allocated in Array.java#createMultiArray
    • 24(allocations) - int[] - allocated in Main.java#OnClick

If you check the statistic you'll se that if i am using 2 dim array the allocated memory is approximately double if i am using 1 dim array. It seems that the extra memory goes for allocating int[].

Does anybody has clear vision why this is happening ?

1

1 Answers

8
votes

This:

new short[2][10]

is creating three objects. It's effectively:

short[][] tmp = new short[2][];
tmp[0] = new short[10];
tmp[1] = new short[10];

Given the overhead of each object, it's not surprising that it's taking about twice as much memory. You would see less difference between this and (say)

// case 1
new short[10000]
// case 2
new short[2][5000]

but the following would be dreadful, as it would create 5000 short[] arrays with only two elements, at which point the overhead dwarfs the actual daa.

new short[5000][2]