title: Faster way to zero memory than with memset?
body: <p>I learned that <code>memset(ptr, 0, nbytes)</code> is really fast, but is there a faster way (at least on x86)?</p>
  
  <p>I assume that memset uses <code>mov</code>, however when zeroing memory most compilers use <code>xor</code> as it's faster, correct? <strong>edit1:</strong> Wrong, as GregS pointed out that only works with registers. What was I thinking?</p>
  
  <p>Also I asked a person who knew of assembler more than me to look at the stdlib, and he told me that on x86 memset is not taking full advantage of the 32 bit wide registers. However at that time I was very tired, so I'm not quite sure I understood it correctly.</p>
  
  <p><strong>edit2</strong>:
  I revisited this issue and did a little testing. Here is what I tested:</p>
  
  <pre><code>    #include &lt;stdio.h&gt;
      #include &lt;malloc.h&gt;
      #include &lt;string.h&gt;
      #include &lt;sys/time.h&gt;
  
      #define TIME(body) do {                                                     \
          struct timeval t1, t2; double elapsed;                                  \
          gettimeofday(&amp;t1, NULL);                                                \
          body                                                                    \
          gettimeofday(&amp;t2, NULL);                                                \
          elapsed = (t2.tv_sec - t1.tv_sec) * 1000.0 + (t2.tv_usec - t1.tv_usec) / 1000.0; \
          printf("%s\n --- %f ---\n", #body, elapsed); } while(0)                 \
  
  
      #define SIZE 0x1000000
  
      void zero_1(void* buff, size_t size)
      {
          size_t i;
          char* foo = buff;
          for (i = 0; i &lt; size; i++)
              foo[i] = 0;
  
      }
  
      /* I foolishly assume size_t has register width */
      void zero_sizet(void* buff, size_t size)
      {
          size_t i;
          char* bar;
          size_t* foo = buff;
          for (i = 0; i &lt; size / sizeof(size_t); i++)
              foo[i] = 0;
  
          // fixes bug pointed out by tristopia
          bar = (char*)buff + size - size % sizeof(size_t);
          for (i = 0; i &lt; size % sizeof(size_t); i++)
              bar[i] = 0;
      }
  
      int main()
      {
          char* buffer = malloc(SIZE);
          TIME(
              memset(buffer, 0, SIZE);
          );
          TIME(
              zero_1(buffer, SIZE);
          );
          TIME(
              zero_sizet(buffer, SIZE);
          );
          return 0;
      }
  </code></pre>
  
  <p>results:</p>
  
  <p><strike>
  zero_1 is the slowest, except for -O3. zero_sizet is the fastest with roughly equal performance across -O1, -O2 and -O3. memset was always slower than zero_sizet. (twice as slow for -O3). one thing of interest is that at -O3 zero_1 was equally fast as zero_sizet. however the disassembled function had roughly four times as many instructions (I think caused by loop unrolling). Also, I tried optimizing zero_sizet further, but the compiler always outdid me, but no surprise here.</strike> </p>
  
  <p>For now memset wins, previous results were distorted by CPU cache. (all tests were run on Linux) Further testing needed. I'll try assembler next :)</p>
  
  <p><strong>edit3:</strong> fixed bug in test code, test results are not affected </p>
  
  <p><strong>edit4:</strong> While poking around the disassembled VS2010 C runtime, I noticed that <code>memset</code> has a SSE optimized routine for zero. It will be hard to beat this.</p>