apr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Justin Erenkrantz <jus...@erenkrantz.com>
Subject [PATCH] Optimized MD5 implementation from OpenSSL
Date Tue, 02 Jan 2007 22:01:02 GMT
One of the bottlenecks that keeps popping up in Subversion is the speed of
the MD5 checksums.  OpenSSL has put in some work to have optimized MD5
implementations and with David's recent work to detect OpenSSL. we can just
defer to their implementations.  For AMD64/EMT64 CPUs, we can leverage
their optimized implementation (which goes from ~250MB/sec to ~370MB/sec).

However, the big annoying thing is that we declared apr_md5_ctx_t in
apr_md5.h so it's not an opaque value.  Luckily for us though, OpenSSL's
MD5 context is smaller than APR's - so an ugly hack works.

OpenSSL's ctx:

#define MD5_CBLOCK»·64
#define MD5_LBLOCK»·(MD5_CBLOCK/4)
#define MD5_DIGEST_LENGTH 16

typedef struct MD5state_st
{
   MD5_LONG A,B,C,D;
   MD5_LONG Nl,Nh;
   MD5_LONG data[MD5_LBLOCK];
   unsigned int num;
} MD5_CTX;

Our context:

struct apr_md5_ctx_t {
    /** state (ABCD) */
    apr_uint32_t state[4];
    /** number of bits, modulo 2^64 (lsb first) */
    apr_uint32_t count[2];
    /** input buffer */
    unsigned char buffer[64];
    /** translation handle·
     *  ignored if xlate is unsupported
     */
    apr_xlate_t *xlate;
};

Using the optimized MD5 implementation tends to shave 5%-10% or so off
Subversion checkout times in rough testing on Solaris 10 AMD64.  

The performance win tells me that it's probably worth it to investigate
this further, but if we can't use OpenSSL's MD5 interface, we need to
duplicate their optimized implementations - which I don't really want to do
unless we have to do so.

Thoughts?  -- justin

Index: crypto/apr_md5.c
===================================================================
--- crypto/apr_md5.c	(revision 491752)
+++ crypto/apr_md5.c	(working copy)
@@ -76,6 +76,39 @@
 #include <pthread.h>
 #endif
 
+#if defined(APU_HAVE_SSL) && !APR_CHARSET_EBCDIC
+
+#include "openssl/md5.h"
+
+APU_DECLARE(apr_status_t) apr_md5_init(apr_md5_ctx_t *context)
+{
+    MD5_Init(context);
+    return APR_SUCCESS;
+}
+
+APU_DECLARE(apr_status_t) apr_md5_set_xlate(apr_md5_ctx_t *context,
+                                            apr_xlate_t *xlate)
+{
+  return APR_ENOTIMPL;
+}
+
+APU_DECLARE(apr_status_t) apr_md5_update(apr_md5_ctx_t *context,
+                                         const void *_input,
+                                         apr_size_t inputLen)
+{
+    MD5_Update(context, _input, inputLen);
+    return APR_SUCCESS;
+}
+
+APU_DECLARE(apr_status_t) apr_md5_final(unsigned char digest[APR_MD5_DIGESTSIZE],
+                                        apr_md5_ctx_t *context)
+{
+    MD5_Final(digest, context);
+    return APR_SUCCESS;
+}
+
+#else
+
 /* Constants for MD5Transform routine.
  */
 
@@ -313,24 +346,6 @@
     return APR_SUCCESS;
 }
 
-/* MD5 in one step (init, update, final)
- */
-APU_DECLARE(apr_status_t) apr_md5(unsigned char digest[APR_MD5_DIGESTSIZE],
-                                  const void *_input,
-                                  apr_size_t inputLen)
-{
-    const unsigned char *input = _input;
-    apr_md5_ctx_t ctx;
-    apr_status_t rv;
-
-    apr_md5_init(&ctx);
-
-    if ((rv = apr_md5_update(&ctx, input, inputLen)) != APR_SUCCESS)
-        return rv;
-
-    return apr_md5_final(digest, &ctx);
-}
-
 /* MD5 basic transformation. Transforms state based on block. */
 static void MD5Transform(apr_uint32_t state[4], const unsigned char block[64])
 {
@@ -452,7 +467,26 @@
                     (((apr_uint32_t)input[j + 2]) << 16) |
                     (((apr_uint32_t)input[j + 3]) << 24);
 }
+#endif
 
+/* MD5 in one step (init, update, final)
+ */
+APU_DECLARE(apr_status_t) apr_md5(unsigned char digest[APR_MD5_DIGESTSIZE],
+                                  const void *_input,
+                                  apr_size_t inputLen)
+{
+    const unsigned char *input = _input;
+    apr_md5_ctx_t ctx;
+    apr_status_t rv;
+
+    apr_md5_init(&ctx);
+
+    if ((rv = apr_md5_update(&ctx, input, inputLen)) != APR_SUCCESS)
+        return rv;
+
+    return apr_md5_final(digest, &ctx);
+}
+
 #if APR_CHARSET_EBCDIC
 APU_DECLARE(apr_status_t) apr_MD5InitEBCDIC(apr_xlate_t *xlate)
 {

Mime
View raw message