Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Copy individual members faster than whole structure?

Tags:

c#

I've got a small structure and have found that copying the individual members is substantially faster than copying the structure in one go. Is there a good reason for this?

My program:

// Some random structure
private struct PackStats
{
    public int nGoodPacks, nBadPacks, nTotalPacks;
}

// ...
PackStats stats1 = new PackStats();
PackStats stats2 = new PackStats();

// Set some random statistics
stats1.nGoodPacks = 55;
stats1.nBadPacks = 3;
stats1.nTotalPacks = (stats1.nGoodPacks + stats1.nBadPacks);

// Now assign stats2 from stats1

// This single line consumes ~190ns...
stats2 = stats1;

// ...but these three lines consume ~100ns (in total)
stats2.nGoodPacks = stats1.nGoodPacks;
stats2.nBadPacks = stats1.nBadPacks;
stats2.nTotalPacks = stats1.nTotalPacks;

To measure times in the nanosecond range, I make the assignments millions of times:

uint uStart = GetTickCount();
for (int nLoop=0; nLoop<10000000; nLoop++)
{
    // Do something...
}
uint uElapsed = (GetTickCount() - uStart);

The results were roughly consistent with both optimisation enabled and disabled...copying individual members of this small structure was about twice as fast. Would the same result apply in C/C++?

like image 715
AlainD Avatar asked Oct 19 '22 08:10

AlainD


1 Answers

Your timings appear to be for a debug build. I did the same test with this code:

    private void DoIt()
    {
        const int numReps = 1000000000;
        PackStats stats1 = new PackStats();
        PackStats stats2 = new PackStats();

        stats1.a = 55;
        stats1.b = 3;
        stats1.c = stats1.a + stats1.b;

        for (var i = 0; i < 2; ++i)
        {
            var sw1 = Stopwatch.StartNew();
            for (var j = 0; j < numReps; ++j)
            {
                stats2 = stats1;
            }
            sw1.Stop();
            Console.WriteLine("Copy struct = {0:N0} ms", sw1.ElapsedMilliseconds);

            sw1.Restart();
            for (var j = 0; j < numReps; ++j)
            {
                stats2.a = stats1.a;
                stats2.b = stats1.b;
                stats2.c = stats1.c;
            }
            sw1.Stop();
            Console.WriteLine("Copy fields = {0:N0} ms", sw1.ElapsedMilliseconds);
        }
    }

My timings are shown below:

                struct       fields
Debug/Debug     2,245        1,908
Debug/No        2,238        1,919
Release/Debug   287          294
Release/No      281          275

This is with Visual Studio 2015. The program is compiled as Any CPU, and run on a 64-bit machine.

Debug/Debug means a debug build run with the debugger attached (i.e. press F5 to run the program). Debug/No means a debug build run without debugging (i.e. Ctrl+F5). And Release, of course, means a release build.

What this tells me is that in release mode, there is virtually no difference between copying a struct all at once, or copying the individual fields. In the worst case shown here, it's 6 milliseconds over a billion iterations.

The answer to your question: "Copy individual members faster than whole structure?" appears to be "In debug mode, yes."

like image 81
Jim Mischel Avatar answered Oct 30 '22 14:10

Jim Mischel