# Memory handling by ConstantArray

I noticed the following issue when using ConstantArray:

a = ConstantArray[0., {10000, 100}];
ByteCount[a]
(* 8000152 *)


Then I set:

a[[1,1]] = 1;
ByteCount[a]
(* 25040080 *)


So to be sure my array will not expand in memory without reason I must multiply each element I want to change by 1.0

Is there another way (more efficient) to ensure I won't change the type of data by accident? Real to Integer shouldn't be a problem...

-
Probably the array was initially packed because it had only one type of data and when another type was introduced was unpacked. Try adding 1. instead of 1 and see what happens. –  Spawn1701D Jun 9 at 19:02

This is not because of ConstantArray, but is because of unpacking due to mixing different types. In short, packed arrays are more memory efficient and can contain only data of one type (Integer, Real or Complex) in regular lists (any dimension). That way, Mathematica need not store the type of each element.

a = ConstantArray[0., {10000, 100}];
DeveloperPackedArrayQ@a
(* True *)

ByteCount[a]
(* 8000152 *)


When you add 1 (an Integer) to a list of Reals, you cause the list to be unpacked, which increases memory usage (since the type of each element is stored).

On["Packing"];
a[[1, 1]] = 1;


During evaluation of In[...]:= DeveloperFromPackedArray::punpack1: Unpacking array with dimensions {10000,100}. >>

ByteCount[a]
(* 25037600 *)

DeveloperPackedArrayQ@a
(* False *)


Try assigning a Real instead:

Clear@a
a = ConstantArray[0., {10000, 100}];
DeveloperPackedArrayQ@a
(* True *)

a[[1, 1]] = 1.;
DeveloperPackedArrayQ@a
(* True *)

ByteCount[a]
(* 8000152 *)

-
For packed arrays the behavior is arguably simpler than in other cases. Since ConstantArray can also return an array of pointers to the element, and given that ByteCount` doesn't take into account which objects are real and which are just references to others, the results could get really confusing. –  Oleksandr R. Jun 9 at 19:49