-1

Hello fellow programmers. So I have a structure, and have come up with 3 different 3D arrays to store it in. Thing is, optimization is not my specialty and I need advice from someone who knows their stuff regarding best ways to store and access multi dimensional arrays of structures. I need to know if any of these methods are better in terms of memory use, or speed of access, etc. when compared to each other. Is there an even better way to store and access the structure aside from arrays that I am not aware of? I mainly used https://msdn.microsoft.com/en-us/library/2s05feca.aspx and other stack overflow posts for reference.

I'm aware that performance and memory use is probably negligible when it comes to small data sets, but the reason I am posting here is because I know that eventually whatever method I choose will be used for very large data sets, and I want to avoid a potential problem down the road.

Currently, I am planning to use one of the methods for a 5 by 8 by X array. I initialized each of the methods below to be 2 by 2 by X, to make it easier to see where items are added.

The three methods are as follows:

Class array nesting - array of items stored in a class that is an array inside another class.

public static Tier3[] _Tier3 = new Tier3[2]

3D full jagged array - an array that is expandable in all three dimensions.

public static Item[][][] _3DjaggedItems = new Item[2][][]

2D rectangular array - a 2D array set in 2 dimensions storing jagged arrays.

public static Item[,][] _2Drectangle_3DjaggedItems = new Item[2,2][]

If you know a better method of storing and accessing this struct, please keep in mind that you must be able to print out "Hello, world!" by assigning values to

public ItemSystem.Item _Item;
public ItemSystem.Item[] _ItemList;

and calling PrintTest(); to print the message.

I'll do my best to answer any questions. Thank you in advance for any help!

Below is the test code I wrote using all three methods to print out "Hello, world!". Just copy paste into C# compiler of choice to run. I used http://rextester.com/

//Rextester.Program.Main is the entry point for your code. Don't change it.
//Compiler version 4.0.30319.17929 for Microsoft (R) .NET Framework 4.5

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace Rextester
{
public class ItemSystem
{
    public struct Item
    {
        public string _1;
        public string _2;
        public string _3;
    }

    public class Tier2
    {
        public Item[] _Items;
    }

    public class Tier3
    {
        public Tier2[] _Tier2;
    }

    //The class of containers the data of which is initialized once.
    public static Tier3[] _Tier3 = new Tier3[2]
    {
        new Tier3()
        {
            _Tier2 = new Tier2[2]
            {
                new Tier2()
                {
                    _Items = new ItemSystem.Item[]
                    {
                        new Item() { _1 = "H", _2 = "e", _3 = "l" },
                        new Item() { _1 = "l", _2 = "o", _3 = "," },
                        new Item() { _1 = " ", _2 = "w", _3 = "o" },
                        new Item() { _1 = "r", _2 = "l", _3 = "d" },
                        new Item() { _1 = "!", _2 = "", _3 = ""   }
                    }
                },
                new Tier2()
                {
                    _Items = new ItemSystem.Item[]
                    {
                        new Item() { _1 = "H", _2 = "e", _3 = "l" }
                    }
                },
            }
        },
        new Tier3()
        {
            _Tier2 = new Tier2[2]
            {
                new Tier2()
                {
                    _Items = new ItemSystem.Item[]
                    {
                        new Item() { _1 = "H", _2 = "e", _3 = "l" }
                    }
                },
                new Tier2()
                {
                    _Items = new ItemSystem.Item[]
                    {
                        new Item() { _1 = "H", _2 = "e", _3 = "l" }
                    }
                },
            }
        },
    };

    public static Item[][][] _3DjaggedItems = new Item[2][][]
    {
        new Item[2][]
        {
            new Item[]
            {
                new Item() { _1 = "H", _2 = "e", _3 = "l" },
                new Item() { _1 = "l", _2 = "o", _3 = "," },
                new Item() { _1 = " ", _2 = "w", _3 = "o" },
                new Item() { _1 = "r", _2 = "l", _3 = "d" },
                new Item() { _1 = "!", _2 = "", _3 = ""   }
            },
            new Item[]
            {
                new Item() { _1 = "H", _2 = "e", _3 = "l" }
            },
        },
        new Item[2][]
        {
            new Item[]
            {
                new Item() { _1 = "H", _2 = "e", _3 = "l" }
            },
            new Item[]
            {
                new Item() { _1 = "H", _2 = "e", _3 = "l" }
            },
        },
    };

    public static Item[,][] _2Drectangle_3DjaggedItems = new Item[2,2][]
    {
        {
            new Item[]
            {
                new Item() { _1 = "H", _2 = "e", _3 = "l" },
                new Item() { _1 = "l", _2 = "o", _3 = "," },
                new Item() { _1 = " ", _2 = "w", _3 = "o" },
                new Item() { _1 = "r", _2 = "l", _3 = "d" },
                new Item() { _1 = "!", _2 = "", _3 = ""   }
            },
            new Item[]
            {
                new Item() { _1 = "H", _2 = "e", _3 = "l" },
            },
        },
        {
            new Item[]
            {
                new Item() { _1 = "H", _2 = "e", _3 = "l" },
            },
            new Item[]
            {
                new Item() { _1 = "H", _2 = "e", _3 = "l" },
            },
        },
    };
}

public class Program
{
    public ItemSystem.Item _Item;
    public ItemSystem.Item[] _ItemList;
    public int _Tier3Accessor = 0;
    public int _Tier2Accessor = 0;
    public void TestFunc()
    {
        _Item     = ItemSystem._Tier3[_Tier3Accessor]._Tier2[_Tier2Accessor]._Items[0];
        _ItemList = ItemSystem._Tier3[_Tier3Accessor]._Tier2[_Tier2Accessor]._Items;

        PrintTest();

        _Item     = ItemSystem._3DjaggedItems[_Tier3Accessor][_Tier2Accessor][0];
        _ItemList = ItemSystem._3DjaggedItems[_Tier3Accessor][_Tier2Accessor];

        PrintTest();

        _Item     = ItemSystem._2Drectangle_3DjaggedItems[_Tier3Accessor, _Tier2Accessor][0];
        _ItemList = ItemSystem._2Drectangle_3DjaggedItems[_Tier3Accessor, _Tier2Accessor];

        PrintTest();
    }

    public void PrintTest()
    {
        for(int i = 0; i < _ItemList.Length; i++)
        {
            Console.Write(_ItemList[i]._1);
            Console.Write(_ItemList[i]._2);
            Console.Write(_ItemList[i]._3);
        }

        Console.WriteLine("\n");
    }

    public static void Main(string[] args)
    {
        Program p = new Program();
        p.TestFunc();
    }
}
}
  • Can you move this to [codereview](http://codereview.stackexchange.com/)? Because there isn't a code problem to fix. – Jeroen van Langen Jan 15 '17 at 18:52
  • Sure, I can post it there as well. I posted the code so whoever attempts to help answer my optimization questions can see exactly what I am doing. – cows_n_muffins Jan 15 '17 at 19:00
  • It depends. Only you know the access patterns: what dimensions are walked with what stride in what order, is access more or less random, will the data be shared among threads that require synchronization, sizes of caches on the target machine, ... . – HABO Jan 15 '17 at 19:22
  • HABO: The main way this will be accessed is to get at the arrays of Item[] at the core of the structure. You can assume that access is more or less random. The data is not shared among threads, but the Item[] arrays will have items added/removed from them. Cache size? Not sure, this code will be running on PCs, and not mobile platforms, so I guess the answer to the cache size question is that it is PC sized. Sorry, I don't know the proper terminology for Cache sizes. – cows_n_muffins Jan 15 '17 at 19:31
  • I suggest [merging the accounts](http://stackoverflow.com/help/merging-accounts). – t3chb0t Jan 15 '17 at 20:46
  • I placed a request to have them merged, sorry about the screw up. – cows_n_muffins Jan 15 '17 at 21:00
  • The fastest way, usually, is one flat array and manual index calculation. That's because it doesn't have the pointer chasing overhead of jagged arrays, and MDarrays have a slow implementation. – harold Jan 16 '17 at 06:07

1 Answers1

0

Figured it out. Did some more searching, and after a while came across these posts

What are the differences between a multidimensional array and an array of arrays in C#?

Why are multi-dimensional arrays in .NET slower than normal arrays?

The short answer is that flattening arrays and then calculating the index you want to access is the fastest way to go. Followed by Jagged arrays, because the Multi Dimensional arrays have a slow implementation in C#.

In terms of formatting, Jagged arrays also allow you to keep a bit more organised due to how they need to be initialized. You could do the same with a flattened array, but you would need to get creative with spacing and commenting to make sure everything is where it should be visually for easy reading.

Community
  • 1
  • 1