Commit 64206728 authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

curl_easy_init: use less mallocs

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.
parent c4067a56
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -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) {
+1 −1
Original line number Diff line number Diff line
@@ -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);

+4 −1
Original line number Diff line number Diff line
@@ -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;
+14 −5
Original line number Diff line number Diff line
@@ -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)
{
+7 −1
Original line number Diff line number Diff line
@@ -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