Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Integer array or struct array - which is better?

In my app, I'm storing Bitmap data in a two-dimensional integer array (int[,]). To access the R, G and B values I use something like this:

// read:
int i = _data[x, y];
byte B = (byte)(i >> 0);
byte G = (byte)(i >> 8);
byte R = (byte)(i >> 16);
// write:
_data[x, y] = BitConverter.ToInt32(new byte[] { B, G, R, 0 }, 0);

I'm using integer arrays instead of an actual System.Drawing.Bitmap because my app runs on Windows Mobile devices where the memory available for creating bitmaps is severely limited.

I'm wondering, though, if it would make more sense to declare a structure like this:

public struct RGB
{
    public byte R;
    public byte G;
    public byte B;
}

... and then use an array of RGB instead of an array of int. This way I could easily read and write the separate R, G and B values without having to do bit-shifting and BitConverter-ing. I vaguely remember something from days of yore about byte variables being block-aligned on 32-bit systems, so that a byte actually takes up 4 bytes of memory instead of just 1 (but maybe this was just a Visual Basic thing).

Would using an array of structs (like the RGB example` above) be faster than using an array of ints, and would it use 3/4 the memory or 3 times the memory of ints?

like image 348
MusiGenesis Avatar asked Mar 14 '10 07:03

MusiGenesis


People also ask

Which is better array or structure?

Structure due to use defined data type become slow in performance as access and searching of element is slower in Structure as compare to Array. On other hand in case of Array access and searching of element is faster and hence better in performance.

Why do we prefer structure over array?

Advantages of Structure over Array:The structure can store different types of data whereas an array can only store similar data types. Structure does not have limited size like an array. Structure elements may or may not be stored in contiguous locations but array elements are stored in contiguous locations.

Whats is the main difference between array & structure?

Definition. Array is a data structure consisting of a collection of elements each identified by the array index while structure is a data type that stores different data types in the same memory location. Thus, this is the main difference between Array and Structure in C programming.

Are structs similar to arrays?

A structure works similar to an array, where we just pack the values next to each other in memory. Structures are useful because, just like with arrays, they allow us to semantically move many related values with a single pointer.


2 Answers

If you are on about speed, then technically I would expect the int[] version to be faster, as there is a specific IL instruction for getting an int from an array (see OpCodes.Ldelem_I4). To do a custom struct it has to get the address (OpCodes.Ldelema) and then copy the struct (OpCodes.Ldobj) - processing the type metadata for both of those steps.

In short - the int approach should have better optimisations. But this is micro-optimisation - in general prefer the version that makes your code more readable. What you might consider is writing the struct with a custom static implicit conversion operator from int to your struct - then you can have the int[] and still do:

MyColor col = intArr[12];

(it'll do a static call in the middle, of course)

You might also consider using a union so you don't need to do lots of shifting:

IMPORTANT I haven't sanity checked the endianness on this; just change the offsets of R/G/B to change it.

class Program
{
    static void Main()
    {
        int[] i = { -1 };
        RGB rgb = i[0];
    }
}
[StructLayout( LayoutKind.Explicit)]
public struct RGB
{
    public RGB(int value) {
        this.R = this.G = this.B = 0; this.Value = value;
    }
    [FieldOffset(0)]
    public int Value;
    [FieldOffset(2)]
    public byte R;
    [FieldOffset(1)]
    public byte G;
    [FieldOffset(0)]
    public byte B;

    public static implicit operator RGB(int value) {
        return new RGB(value);
    }
    public static implicit operator int(RGB value) {
        return value.Value;
    }
}
like image 82
Marc Gravell Avatar answered Oct 13 '22 07:10

Marc Gravell


A lone byte on its own would probably get block-aligned, but multiple bytes in a struct can be packed. And according to Marshal.SizeOf, your RGB struct does indeed occupy only three bytes of memory. (Technically, this is the size when marshalling to unmanaged memory, and the CLR could choose to lay it out differently; but in practice I think this will be correct.)

However, the CLR could still insert padding between RGBs and other structs, and this behaviour may depend on the processor, CLR version etc. On a x86 system, allocating an array of 300 million RGB resulted in Task Manager reporting approximately 900 MB committed, whereas allocating an array of 300 million ints resulted in 1200 MB committed. So it looks like the 2.0 CLR on x86 is giving you the 25% saving. (I have to admit this surprised me; like Traveling Tech Guy, I expected the 3-byte structs to be aligned to a 4-byte boundary. So I may be missing something.) But the CF may be different: you'll really only know by testing it on your target platform.

like image 30
itowlson Avatar answered Oct 13 '22 06:10

itowlson