Memory access patterns in high-level languages

Like many developers that work in high-level languages, I think don’t spend a lot of time thinking about memory access patterns. This is probably a good thing… for the most part, worrying about this is premature optimization. But there are times when it matters, and the compiler won’t magically “optimize” it away for you, even if you have optimizations turned on:

Code

class MemoryAccessPatterns
{
    static void Main(string[] args)
    {
        var timer = new Stopwatch();
 
        timer.Start();
        for (var i = 0; i < 25; i++)
        {
            doFast();
        }
        timer.Stop();
        Console.WriteLine("Fast array: {0}", timer.ElapsedMilliseconds);
 
        timer.Restart();
        for (var i = 0; i < 25; i++)
        {
            doSlow();
        }
        timer.Stop();
        Console.WriteLine("Slow array: {0}", timer.ElapsedMilliseconds);
        Console.ReadKey();
    }
 
    private static void doFast()
    {
        var fast = new int[5000, 5000];
        for (var i = 0; i < 5000; i++)
        {
            for (var j = 0; j < 5000; j++)
            {
                fast[i, j]++;
            }
        }
    }
 
    private static void doSlow()
    {
        var slow = new int[5000, 5000];
        for (var i = 0; i < 5000; i++)
        {
            for (var j = 0; j < 5000; j++)
            {
                slow[j, i]++;
            }
        }
    }
}

Results

Release x86, optimizations on:
Fast array: 3829
Slow array: 8495

Release x86, optimizations off:
Fast array: 4357
Slow array: 8675

Release x64, optimizations on:
Fast array: 5074
Slow array: 10445

Release x64, optimizations off:
Fast array: 5954
Slow array: 10781

I tried this out after seeing this discussion thread on Quora this morning.

Leave a Reply

Your email address will not be published. Required fields are marked *