title: Why is MD5Sum so fast
body: <p>I've been studying hashing in C/C++ and tried to replicate the md5sum command in Linux. After analysing the source code, it seems that md5sum relies on the md5 library's md5_stream. I've approximated the md5_stream function from the md5.h library into the code below, and it runs in ~13-14 seconds. I've tried to call the md5_stream function directly and got ~13-14 seconds. The md5sum runs in 4 seconds. What have the GNU people done to get the speed out of the code?</p>
  
  <p>The md5.h/md5.c code is available in the CoreUtils source code.</p>
  
  <pre><code>#include &lt;QtCore/QCoreApplication&gt;
  #include &lt;QtCore/QDebug&gt;
  
  #include &lt;iostream&gt;
  #include &lt;iomanip&gt;
  #include &lt;fstream&gt;
  #include "md5.h"
  
  #define BLOCKSIZE 32784
  
  int main()
  {
      FILE *fpinput, *fpoutput;
  
      if ((fpinput = fopen("/dev/sdb", "rb")) == 0) {
          throw std::runtime_error("input file doesn't exist");
      }
  
      struct md5_ctx ctx;
      size_t sum;
  
      char *buffer = (char*)malloc (BLOCKSIZE + 72);
      unsigned char *resblock = (unsigned char*)malloc (16);
      if (!buffer)
        return 1;
  
      md5_init_ctx (&amp;ctx);
      size_t n;
      sum = 0;
  
      while (!ferror(fpinput) &amp;&amp; !feof(fpinput)) {
          n = fread (buffer + sum, 1, BLOCKSIZE - sum, fpinput);
          if (n == 0){
              break;
          }
          sum += n;
  
          if (sum == BLOCKSIZE) {
              md5_process_block (buffer, BLOCKSIZE, &amp;ctx);
              sum = 0;
          }
      }
  
      if (n == 0 &amp;&amp; ferror (fpinput)) {
          free (buffer);
          return 1;
      }
  
      /* Process any remaining bytes.  */
      if (sum &gt; 0){
        md5_process_bytes (buffer, sum, &amp;ctx);
      }
  
      /* Construct result in desired memory.  */
      md5_finish_ctx (&amp;ctx, resblock);
      free (buffer);
  
      for (int x = 0; x &lt; 16; ++x){
          std::cout &lt;&lt; std::setfill('0') &lt;&lt; std::setw(2) &lt;&lt; std::hex &lt;&lt; static_cast&lt;uint16_t&gt;(resblock[x]);
          std::cout &lt;&lt; " ";
      }
      std::cout &lt;&lt; std::endl;
      free(resblock);
      return 0;
  }
  </code></pre>
  
  <p>EDIT: Was a default mkspec problem in Fedora 19 64-bit.</p>