Allocating Jagged Array C#

86 Views Asked by At

It seems like there is no good way to allocate a jagged array in C#. It takes several orders of magnitude longer to allocate a jagged array than to allocate a 2D array. Is there any way around this? Is there a better way? I want the allocation of the jagged array to be similar in time the allocation of the 2D array.

Edit: To be clear, every byte array in the jagged array will be length 8. But the 2D array does not work, because I cannot pass it to the API that I need to pass it to. The API I need to use takes an array of byte arrays.

This takes 20 seconds:

public void CreateHashByte()
{
    byte[][] holder = new byte[100000000][];
    for (int k = 0; k < 100000000; k++)
    {
        holder[k] = new byte[8];
    }
}

This is almost instantaneous:

public void CreateHashByte2()
{
    byte[,] holder = new byte[100000000, 8];
}

Edit 2: This is pretty fast, about a half second, but it requires me to rewrite the API to unwrap the byte array. A half second still seems like a long time to just set aside a GB of memory.

public class Hbyte
{
    public byte[] data { get; set; } = new byte[8];
}

public Hbyte[] CreateHashByte3()
{
    Hbyte[] holder = new Hbyte[100000000];
    return holder;
}
1

There are 1 best solutions below

1
Luke Vo On

Using 1D array is faster but you need extra space to manage the indices (or else without it the access would take a long time to know where any element is at).

For my test (ms is the unit):

Jagged Array took 8418
1D Array took 397

using System.Diagnostics;

const int TestLength = (int)1E8;
var lengths = new int[TestLength];
for (int i = 0; i < TestLength; i++)
{
    lengths[i] = i % 10;
}

var timer = new Stopwatch();

// Using C# jagged array
timer.Restart();
var arr1 = new byte[TestLength][];
for (int i = 0; i < TestLength; i++)
{
    arr1[i] = new byte[lengths[i]];
}

Console.WriteLine("Jagged Array took " + timer.ElapsedMilliseconds);

// Using 1d array
timer.Restart();
var indices = new long[TestLength]; // You can reuse the lengths array
long currIndex = 0;
for (int i = 0; i < TestLength; i++)
{
    indices[i] = currIndex;
    currIndex += lengths[i];
}

var arr2 = new byte[currIndex];

Console.WriteLine("1D Array took " + timer.ElapsedMilliseconds);

// To use 1d array:
var valueAt21 = arr2[indices[2] + 1];