For the Float64 array ar2, the size is straightforward: 50 * 50 * 50 elements, and a 64-bit float takes 8 bytes, so that’s 1 MB. Then 56 bytes of overhead for the array itself.
For the AbstractFloat array ar1, it’s not possible to determine the size of every element in the array. The user can always define a new type MyType <: AbstractFloat with whatever size the user wants. Therefore, Julia needs to store every float individually on the heap, and then fill the array itself with pointers to those floats on the heap.
So, we have 50 * 50 * 50 = 125,000 floats. Each of these take up 8 bytes on the heap (plus some overhead which is somehow not counted) for 1 MB total, and then the array itself takes up 50 * 50 * 50 8-byte pointer for another 1 MB total. Then the 56 byte overhead for the array.