2016-05-26 11 views
5

Mam małą strukturę i odkryłem, że kopiowanie poszczególnych elementów jest znacznie szybsze niż kopiowanie struktury za jednym razem. Czy istnieje ku temu dobry powód?Skopiuj pojedyncze elementy szybciej niż cała struktura?

Mój 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; 

Do pomiaru czasu w zakresie nanosekund, robię przypisania miliony razy:

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

Wyniki były mniej więcej zgodne zarówno z włączoną optymalizacją i niepełnosprawnych .. Kopiowanie poszczególnych członków tej małej struktury było około dwa razy szybsze. Czy ten sam wynik miałby zastosowanie w C/C++?

+0

Tutaj był komentarz na temat sprawdzania kodu IL. Nie jestem pewien, jak to zrobić i będę badać, jak to zrobić. Jeśli jest to łatwe do wyjaśnienia, proszę odpowiedzieć komentarzem. – AlainD

+0

http://stackoverflow.com/q/9025186/11683 – GSerg

+0

64-bitowy procesor, skompilowany dla anycpu? –

Odpowiedz

3

Twoje czasy wydają się być na kompilację debugowania. Zrobiłem ten sam test z tego kodu:

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); 
     } 
    } 

Moje czasy są przedstawione poniżej:

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

to z Visual Studio 2015. Program został skompilowany jako dowolny CPU, i działać na 64- maszyna bitowa.

Debugowanie/debugowanie oznacza uruchomienie kompilacji debugowania z dołączonym debuggerem (tj. Naciśnięcie klawisza F5 w celu uruchomienia programu). Debugowanie/Nie oznacza wykonanie kompilacji debugowania bez debugowania (np. Ctrl + F5). A Release, oczywiście, oznacza kompilację wydania.

To, co mi to mówi, to to, że w trybie zwolnienia nie ma praktycznie żadnej różnicy między kopiowaniem struktury na raz lub kopiowaniem poszczególnych pól. W najgorszym przypadku pokazanym tutaj jest to 6 milisekund ponad miliard iteracji.

Odpowiedź na pytanie: "Skopiuj poszczególnych członków szybciej niż całą strukturę?" wygląda na "W trybie debugowania, tak".

+1

Wydaje się, że VS 2015 wykonuje doskonałą, lepszą pracę przy optymalizacji w trybie Release, więc te wyniki są zachęcające, dziękuję (korzystałem z VS 2008). Wcześniejsza odpowiedź wskazywała, że ​​nowa struktura została utworzona przy użyciu 'stats2 = stats1;', ale odpowiedź została teraz usunięta. Sądzę, że to wiąże się z twoimi wynikami - skuteczny optymalizator prawdopodobnie nie będzie niepotrzebnie tworzyć nowej struktury. – AlainD

Powiązane problemy