curl_easy_init: use less mallocs
authorDaniel Stenberg <daniel@haxx.se>
Fri, 26 Apr 2013 20:23:08 +0000 (22:23 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Fri, 26 Apr 2013 20:55:55 +0000 (22:55 +0200)
By introducing an internal alternative to curl_multi_init() that accepts
parameters to set the hash sizes, easy handles will now use tiny socket
and connection hash tables since it will only ever add a single easy
handle to that multi handle.

This decreased the number mallocs in test 40 (which is a rather simple
and typical easy interface use case) from 1142 to 138. The maximum
amount of memory allocated used went down from 118969 to 78805.

lib/conncache.c
lib/conncache.h
lib/easy.c
lib/multi.c
lib/multiif.h

index 530cdc2ec3f4183429e8d76c2dfe73515e8d951a..48271f7510ff545106ab8fb130526925fc584b60 100644 (file)
@@ -38,8 +38,6 @@
 /* The last #include file should be: */
 #include "memdebug.h"
 
-#define CONNECTION_HASH_SIZE 97
-
 static void free_bundle_hash_entry(void *freethis)
 {
   struct connectbundle *b = (struct connectbundle *) freethis;
@@ -47,7 +45,7 @@ static void free_bundle_hash_entry(void *freethis)
   Curl_bundle_destroy(b);
 }
 
-struct conncache *Curl_conncache_init(void)
+struct conncache *Curl_conncache_init(int size)
 {
   struct conncache *connc;
 
@@ -55,7 +53,7 @@ struct conncache *Curl_conncache_init(void)
   if(!connc)
     return NULL;
 
-  connc->hash = Curl_hash_alloc(CONNECTION_HASH_SIZE, Curl_hash_str,
+  connc->hash = Curl_hash_alloc(size, Curl_hash_str,
                                 Curl_str_key_compare, free_bundle_hash_entry);
 
   if(!connc->hash) {
index fad17d8f7a76d44c4830460a5f526dbd1fa76bfa..f5e41f187b69a8b7d45546a77cf69c27e264d38f 100644 (file)
@@ -27,7 +27,7 @@ struct conncache {
   size_t num_connections;
 };
 
-struct conncache *Curl_conncache_init(void);
+struct conncache *Curl_conncache_init(int size);
 
 void Curl_conncache_destroy(struct conncache *connc);
 
index 72e1206f4b61fcde33d6472794b5df75d6d042a0..eb45bd717f2ada4dbff6b73ed6bf63e453c8d108 100644 (file)
@@ -73,6 +73,7 @@
 #include "non-ascii.h"
 #include "warnless.h"
 #include "conncache.h"
+#include "multiif.h"
 
 #define _MPRINTF_REPLACE /* use our functions only */
 #include <curl/mprintf.h>
@@ -437,7 +438,9 @@ CURLcode curl_easy_perform(CURL *easy)
   if(data->multi_easy)
     multi = data->multi_easy;
   else {
-    multi = curl_multi_init();
+    /* this multi handle will only ever have a single easy handled attached
+       to it, so make it use minimal hashes */
+    multi = Curl_multi_handle(1, 3);
     if(!multi)
       return CURLE_OUT_OF_MEMORY;
     data->multi_easy = multi;
index 7d795cf3ddbb4892064788aeb2f53a1816471059..77262fc34950595ef901ebe6c4a2e44061ac4cc4 100644 (file)
@@ -58,6 +58,7 @@
 #define CURL_SOCKET_HASH_TABLE_SIZE 911
 #endif
 
+#define CURL_CONNECTION_HASH_SIZE 97
 
 #define CURL_MULTI_HANDLE 0x000bab1e
 
@@ -246,9 +247,9 @@ static size_t hash_fd(void *key, size_t key_length, size_t slots_num)
  * per call."
  *
  */
-static struct curl_hash *sh_init(void)
+static struct curl_hash *sh_init(int hashsize)
 {
-  return Curl_hash_alloc(CURL_SOCKET_HASH_TABLE_SIZE, hash_fd, fd_key_compare,
+  return Curl_hash_alloc(hashsize, hash_fd, fd_key_compare,
                          sh_freeentry);
 }
 
@@ -278,7 +279,8 @@ static void multi_freeamsg(void *a, void *b)
   (void)b;
 }
 
-CURLM *curl_multi_init(void)
+struct Curl_multi *Curl_multi_handle(int hashsize, /* socket hash */
+                                     int chashsize) /* connection hash */
 {
   struct Curl_multi *multi = calloc(1, sizeof(struct Curl_multi));
 
@@ -291,11 +293,11 @@ CURLM *curl_multi_init(void)
   if(!multi->hostcache)
     goto error;
 
-  multi->sockhash = sh_init();
+  multi->sockhash = sh_init(hashsize);
   if(!multi->sockhash)
     goto error;
 
-  multi->conn_cache = Curl_conncache_init();
+  multi->conn_cache = Curl_conncache_init(chashsize);
   if(!multi->conn_cache)
     goto error;
 
@@ -325,6 +327,13 @@ CURLM *curl_multi_init(void)
   return NULL;
 }
 
+CURLM *curl_multi_init(void)
+{
+  return Curl_multi_handle(CURL_SOCKET_HASH_TABLE_SIZE,
+                           CURL_CONNECTION_HASH_SIZE);
+}
+
+
 CURLMcode curl_multi_add_handle(CURLM *multi_handle,
                                 CURL *easy_handle)
 {
index 0dcdec76e0b3a3492f93cba25a6a2a365a6fd385..799daebcc195f0dc3b278ce048b0851a3989dd1b 100644 (file)
@@ -7,7 +7,7 @@
  *                            | (__| |_| |  _ <| |___
  *                             \___|\___/|_| \_\_____|
  *
- * Copyright (C) 1998 - 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2013, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -22,6 +22,8 @@
  *
  ***************************************************************************/
 
+
+
 /*
  * Prototypes for library-wide functions provided by multi.c
  */
@@ -30,6 +32,10 @@ void Curl_expire(struct SessionHandle *data, long milli);
 bool Curl_multi_pipeline_enabled(const struct Curl_multi* multi);
 void Curl_multi_handlePipeBreak(struct SessionHandle *data);
 
+/* Internal version of curl_multi_init() accepts size parameters for the
+   socket and connection hashes */
+struct Curl_multi *Curl_multi_handle(int hashsize, int chashsize);
+
 /* the write bits start at bit 16 for the *getsock() bitmap */
 #define GETSOCK_WRITEBITSTART 16