title: CPU usage C Packed struct vs Unsigned Long Long operations
body: <p>I need to do some operations with 48 bit variables, so I had two options: </p>
  
  <ol>
  <li>Create my own structure with 48 bit variables, or </li>
  <li>Use <strong>unsigned long long</strong> (64 bits). </li>
  </ol>
  
  <p>As the operations will not overflow 48 bits, I considered that using 64 bit variables was an overkill, so I created a base structure </p>
  
  <pre><code>#ifdef __GNUC__
  #define PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__))
  #endif
  
  #ifdef _MSC_VER
  #define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop))
  #endif
  
  PACK(struct uint48 {
      unsigned long long v : 48;
  });
  </code></pre>
  
  <p>and created some code to check for speed in the operations</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;time.h&gt;
  
  #ifdef __GNUC__
  #define PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__))
  #endif
  
  #ifdef _MSC_VER
  #define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop))
  #endif
  
  PACK(struct uint48 {
      unsigned long long v : 48;
  });
  
  
  void TestProductLong();
  void TestProductLong02();
  
  void TestProductPackedStruct();
  void TestProductPackedStruct02();
  
  clock_t start, end;
  double cpu_time_used;
  int cycleNumber = 100000;
  
  int main(void)
  {
      TestProductLong();
      TestProductLong02();
  
      TestProductPackedStruct();
      TestProductPackedStruct02();
  
      return 0;
  }
  
  
  void TestProductLong() {
  
      start = clock();
  
      for (int i = 0; i &lt; cycleNumber;i++) {
          unsigned long long varlong01 = 155782;
          unsigned long long varlong02 = 15519994;
          unsigned long long product01 = varlong01 * varlong02;
  
          unsigned long long varlong03 = 155782;
          unsigned long long varlong04 = 15519994;
          unsigned long long product02 = varlong03 * varlong04;
  
          unsigned long long addition = product01 + product02;
      }
  
      end = clock();
      cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
  
      printf("TestProductLong() took %f seconds to execute \n", cpu_time_used);
  }
  
  
  void TestProductLong02() {
  
      start = clock();
  
      unsigned long long varlong01;
      unsigned long long varlong02;
      unsigned long long product01;
  
      unsigned long long varlong03;
      unsigned long long varlong04;
      unsigned long long product02;
  
      unsigned long long addition;
  
      for (int i = 0; i &lt; cycleNumber;i++) {
          varlong01 = 155782;
          varlong02 = 15519994;
          product01 = varlong01 * varlong02;
  
          varlong03 = 155782;
          varlong04 = 15519994;
          product02 = varlong03 * varlong04;
  
          addition = product01 + product02;
      }
  
      end = clock();
      cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
  
      printf("TestProductLong02() took %f seconds to execute \n", cpu_time_used);
  }
  
  
  void TestProductPackedStruct() {
  
      start = clock();
  
      for (int i = 0; i &lt; cycleNumber; i++) {
          struct uint48 x01;
          struct uint48 x02;
          struct uint48 x03;
  
          x01.v = 155782;
          x02.v = 15519994;
          x03.v = x01.v * x02.v;
  
          struct uint48 x04;
          struct uint48 x05;
          struct uint48 x06;
  
          x04.v = 155782;
          x05.v = 15519994;
          x06.v = x04.v * x05.v;
  
          struct uint48 x07;
  
          x07.v = x03.v + x06.v;
      }
  
      end = clock();
      cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
  
      printf("TestProductPackedStruct() took %f seconds to execute \n", cpu_time_used);
  }
  
  
  void TestProductPackedStruct02() {
  
      start = clock();
  
      struct uint48 x01;
      struct uint48 x02;
      struct uint48 x03;
      struct uint48 x04;
      struct uint48 x05;
      struct uint48 x06;
      struct uint48 x07;
  
      for (int i = 0; i &lt; cycleNumber; i++) {
  
          x01.v = 155782;
          x02.v = 15519994;
          x03.v = x01.v * x02.v;
  
          x04.v = 155782;
          x05.v = 15519994;
          x06.v = x04.v * x05.v;
  
          x07.v = x03.v + x06.v;
      }
  
      end = clock();
      cpu_time_used = ((double)(end - start)) / CLOCKS_PER_SEC;
  
      printf("TestProductPackedStruct02() took %f seconds to execute \n", cpu_time_used);
  }
  </code></pre>
  
  <p>But I got the following results</p>
  
  <pre><code>TestProductLong() took 0.000188 seconds to execute 
  TestProductLong02() took 0.000198 seconds to execute 
  TestProductPackedStruct() took 0.001231 seconds to execute 
  TestProductPackedStruct02() took 0.001231 seconds to execute
  </code></pre>
  
  <p>So the operations using <strong>unsigned long long</strong> took less time than the ones using the packed structure. </p>
  
  <ul>
  <li>Why is that? </li>
  <li>Would be better then to use the <strong>unsigned long long</strong> instead? </li>
  <li>Is there a better way to pack structures?</li>
  </ul>
  
  <p>As I'm right now unrolling loops, using the correct datastructure could impact the performance of my application significantly. </p>
  
  <p>Thank you.</p>